安得萬里風(fēng),飄飖吹我裳。
唐 杜甫 《夏夜嘆》
摘要
目前使用 git 作為文件版本控制工具的開發(fā)者越來越多,同時(shí)一個(gè)開發(fā)者可以擁有多個(gè)不同 git 服務(wù)器的帳號(hào)或者同一個(gè) git 服務(wù)器的不同帳號(hào)。
??例如,小明在公司有個(gè)公司搭建的 git 服務(wù)器帳號(hào)用于工作開發(fā),同時(shí)在目前流行的 github 和 bitbucket 上也有帳號(hào),在業(yè)余時(shí)間 fork 一些項(xiàng)目,然后做一些 contributes. 這時(shí)小明就會(huì)遇到一個(gè)問題,賬戶這么多,如果每次使用 git 軟件在終端進(jìn)行 add, commit 后,需要 push 到本地倉庫對應(yīng)的遠(yuǎn)程服務(wù)器時(shí),如果沒有事先配置好 ssh 免密碼登錄或是其他密鑰管理方法, 每次都需要輸入對應(yīng)的服務(wù)器賬戶密碼來進(jìn)行安全認(rèn)證。
??有沒有什么方法可以一勞永逸地解決這個(gè)多 git 賬戶自動(dòng)匹配免密碼登錄問題呢?
本文描述了在 Terminal 環(huán)境下使用 ssh 協(xié)議的多個(gè)不同 git 服務(wù)器帳號(hào)的 git 倉庫如何自動(dòng)匹配免密碼登錄的方法。
快速預(yù)覽
主要解決兩個(gè)問題,免密碼登錄 和 多賬戶自動(dòng)匹配,前者可以使用 ssh 公私鑰對解決,后者通過編輯 ssh 配置文件解決。
場景模擬
小明目前有 3 個(gè) git 服務(wù)器賬戶,賬戶信息分別如下:
- 第 1 個(gè)是公司購買的 bitbucket 付費(fèi)賬戶,用于日常工作開發(fā), 其賬戶名為
xiaoming
, 關(guān)聯(lián)郵箱為xiaoming@test.com
,
目前工作項(xiàng)目的倉庫地址為git@bitbucket.org:xiaoming/testFly.git
. - 第 2 個(gè)是自己私人申請的免費(fèi) bitbucket 賬戶, 用于管理和保存私人的配置文件等或者 fork 一些項(xiàng)目研究做些貢獻(xiàn),其賬戶名為
superming
,關(guān)聯(lián)郵箱為
superming@gmail.com
, 目前關(guān)注的項(xiàng)目倉庫地址是git@bitbucket.org:superming/superman.git
. - 第 3 個(gè)賬戶也是自己私人申請的免費(fèi) github 賬戶,這里是開源的天堂,小明經(jīng)常在此 star, watch, fork 項(xiàng)目等,其賬戶名為
mingh
, 關(guān)聯(lián)郵箱為
mingh@gmail.com
.
為了實(shí)現(xiàn)這 3 個(gè)賬戶自動(dòng)匹配免密碼登錄,小明首先依次生成了三對密鑰文件:
# 生成第 1 個(gè)名為 xiaoming 賬戶的密鑰對
$ssh-keygen -t rsa -f ~/.ssh/id_rsa_xiaoming -C "xiaoming@test.com"
# 生成第 2 個(gè)名為 superming 賬戶的密鑰對
$ssh-keygen -t rsa -f ~/.ssh/id_rsa_superming -C "superming@gmail.com"
# 生成第 3 個(gè)名為 mingh 賬戶的密鑰對
$ssh-keygen -t rsa -f ~/.ssh/id_rsa_mingh -C "mingh@gmail.com"
接著手動(dòng)添加了這 3 對密鑰對的私鑰文件到 ssh-agent
會(huì)話用于自動(dòng)認(rèn)證 ssh
會(huì)話連接:
$ssh-add ~/.ssh/id_rsa_xiaoming
$ssh-add ~/.ssh/id_rsa_superming
$ssh-add ~/.ssh/id_rsa_mingh
由于 ssh-agent
會(huì)話是一個(gè)臨時(shí)的會(huì)話,在終端退出后也隨之結(jié)束,為了每次啟動(dòng)終端時(shí)都能自動(dòng)添加私鑰文件:
$echo "ssh-add ~/.ssh/id_rsa_xiaoming >/dev/null 2&1" >> ~/.bashrc
$echo "ssh-add ~/.ssh/id_rsa_superming >/dev/null 2&1" >> ~/.bashrc
$echo "ssh-add ~/.ssh/id_rsa_mingh >/dev/null 2&1" >> ~/.bashrc
由于小明用的是 zshell
, 需要把 ~/.bashrc
改成 ~/.zshrc
.
接下來就要配置 ~/.ssh/config
配置文件實(shí)現(xiàn)賬戶自動(dòng)匹配:
# 第 1 個(gè) xiaoming bitbucket 工作賬戶
host xiaoming_work
hostname bitbucket.org
Port 22
User git
IdentityFile "~/.ssh/id_rsa_xiaoming"
# 第 2 個(gè) superming bitbucket 私人賬戶
host bitbucket.org
hostname bitbucket.org
Port 22
User git
IdentityFile "~/.ssh/id_rsa_superming"
# 第 3 個(gè) mingh github 私人賬戶
host github.com
hostname github.com
Port 22
User git
IdentityFile "~/.ssh/id_rsa_mingh"
由于工作賬戶新項(xiàng)目創(chuàng)建不頻繁,所以使用了 xiaoming_work
作為 host
, 但同時(shí)需要到當(dāng)前工作的項(xiàng)目的根目錄修改遠(yuǎn)程服務(wù)器地址:
# 原遠(yuǎn)程服務(wù)器 origin 地址為 git@bitbucket:xiaoming/testFly.git
$git remote remove origin
$git remote add origin xiaoming_work:xiaoming/testFly.git
而 host
與 hostname
一致的兩個(gè)常用賬戶則不需要修改遠(yuǎn)程服務(wù)器地址了。
為了保證對應(yīng)賬戶下的 git 倉庫使用對應(yīng)的賬戶名和郵箱進(jìn)行 commit
, push
等,
還需要進(jìn)行每個(gè) git 倉庫設(shè)置對應(yīng)的 user.name
和 user.email
:
$cd <testFly 倉庫根目錄>
$git config --local user.name "xiaoming"
$git config --local user.email "xiaoming@test.com"
...
## 其他倉庫類似配置
方法詳解
-
為指定 git 賬戶生成 ssh 密鑰文件實(shí)現(xiàn)免密碼登錄
ssh-keygen -t rsa -f ~/.ssh/id_rsa_work -C "work@163.com"`
-
-t rsa
指定生成密鑰類型(type)為 rsa 非對稱加密; -
-f ~/.ssh/id_rsa_work
指定生成密鑰存放文件(file)為~/.ssh/id_rsa_work
, 該文件名可以由用戶自己命名,
建議該文件統(tǒng)一放在~/.ssh/
目錄下以便于管理; -
-C "work@163.com"
給該密鑰添加注釋(comment),一般使用關(guān)聯(lián)該 git 賬戶的 email.
執(zhí)行此命令后需要你輸入要生成的密鑰文件的口令(密碼)和重復(fù)輸入口令,連按回車鍵即可設(shè)置密鑰文件口令為空從而實(shí)現(xiàn)免密碼登錄。
然后你就會(huì)在~/.ssh
目錄下找到新生成的密鑰文件分別為id_rsa_work
和id_rsa_work.pub
, 前者為私鑰文件,本地私人使用,后者為公鑰文件,
可以公開使用。
-
-
添加上述私鑰文件到當(dāng)前 ssh-agent 會(huì)話用于認(rèn)證 ssh 會(huì)話
ssh-add ~/.ssh/id_rsa_work
-
查看當(dāng)前會(huì)話已添加的 ssh 私鑰
ssh-add -L
-
每次啟動(dòng)終端時(shí)都自動(dòng)添加指定私鑰到當(dāng)前 ssh-agent 會(huì)話中
echo "ssh-add ~/.ssh/id_rsa_work >/dev/null 2>&1" >> ~/.bashrc
如果使用 zshell
echo "ssh-add ~/.ssh/id_rsa_work >/dev/null 2>&1" >> ~/.zshrc
-
配置
~/.ssh/config
文件實(shí)現(xiàn)多 git 賬戶自動(dòng)匹配認(rèn)證登錄
編輯~/.ssh/config
ssh 配置文件(如果沒有該文件就手動(dòng)新建,touch ~/.ssh/config
),
以 bitbucket 帳戶為例,例如賬戶work
下的一個(gè) git 倉庫地址為:git@bitbucket.org:work/test.git
, 從倉庫地址可以看出此倉庫的
用戶名(User
)為git
, 主機(jī)名(hostname
)為bitbucket.org
, 通信端口號(hào)(Port
)一般為22
.所以其配置為:# 此處演示 bitbucket 下注冊的賬戶名為 work 的賬戶的 ssh 配置 host git@bitbucket.org # 主機(jī)別名,用戶自定義,具有唯一性 hostname bitbucket.org # git 遠(yuǎn)程服務(wù)器主機(jī)名 Port 22 # git 服務(wù)器端口號(hào),一般默認(rèn)為 22 User git # git 倉庫地址中 @ 符號(hào)前的用戶名,常見為 git, 注意與你在該服務(wù)器上申請的賬戶名區(qū)分 IdentityFile "~/.ssh/id_rsa_work" # 剛開始生成的密鑰文件存放位置
其中
hostname
,User
,Port
對應(yīng)于 git 倉庫地址里的信息,而host
可以認(rèn)為是一個(gè)別名,表示了這一主機(jī)的別名,
可隨意命名,用于區(qū)分具有同一個(gè)hostname
的不同賬戶的倉庫。IdentityFile
為私鑰認(rèn)證文件,即上文生成的id_rsa_work
文件. -
部署公鑰到 git 服務(wù)器
例如在 bitbucket 服務(wù)器網(wǎng)頁上菜單bitbucket Settings > SSH keys > Add key
,
把公鑰文件里的公鑰字符串拷貝粘貼到此處設(shè)置處.# 拷貝公鑰字符串到系統(tǒng)剪貼板,此處是 macOS 的系統(tǒng)剪貼板 cat ~/.ssh/id_rsa_work.pub | pbcopy
-
測試 ssh 能否免密碼直連
ssh -vT git@bitbucket.org
或者使用
git clone
一個(gè)當(dāng)前賬戶下的私人項(xiàng)目到本地看是否成功。 修改本地 git 倉庫的遠(yuǎn)程服務(wù)器地址
- 如果你在 github 或者 bitbucket 服務(wù)器上都只注冊了一個(gè)賬戶,在配置
~/.ssh/config
時(shí)建議host
與hostname
保持一致,
如此不用修改配置。 - 如果你在同一個(gè) git 服務(wù)器上有兩個(gè)賬戶,例如在 bitbucket 上有常用的
work
賬戶和不太常用的life
賬戶,~/.ssh/config
可以配置如下:# personal git account "work" in bitbucket host git@bitbucket.org hostname bitbucket.org Port 22 User git IdentityFile "~/.ssh/id_rsa_work" # personal git account "life" in bitbucket host lifebucket hostname bitbucket.org Port 22 User git IdentityFile "~/.ssh/id_rsa_life"
- 使用上述配置,對于要新
clone
的work
賬戶下的倉庫或是本地已存在的倉庫,不需要修改任何配置,因?yàn)?host
與hostname
一樣。 - 對于
life
賬戶下的倉庫:- 新 clone 的倉庫需要修改倉庫地址url,例如
git clone git@bitbucket.org:life/tutorial.git
改為git clone lifebucket:life/tutorial.git
- 已經(jīng)存在的倉庫,切換到該倉庫根目錄,執(zhí)行
git remote remove origin && git remote add origin lifebucket:life/tutorial.git
.
- 新 clone 的倉庫需要修改倉庫地址url,例如
- 使用上述配置,對于要新
- git 設(shè)置
由于有多個(gè)不同的 git 賬戶,一般不能隨意設(shè)置 git 全局設(shè)置了,尤其是user.name
和user.email
,需要單獨(dú)給每個(gè)倉庫設(shè)置。
首先移除全局設(shè)置:
git config --global --unset user.name && git config --global --unset user.email
,
然后到對應(yīng)的倉庫根目錄下執(zhí)行類似于下面的命令:git config --local user.name "life" git config --local user.email "life@163.com"