Updated at [2017-12-27 水 16:58]
後來覺得這篇文章原本講的方法實在太麻煩了,而且當你有用 submodule 時會有問題 (總不能直接改 submodule 的 git repo URL 吧),剛好發現一個好辦法:使用環境變數
GIT_SSH_COMMAND
,如下:
1 GIT_SSH_COMMAND="ssh -i ~/.ssh/COMPANY_KEY" git clone git@github.com:foo/bar
但這樣每次都要打前面那一串很麻煩,不如直接
export
,例如我自己是寫了個簡單的 alias 到~/.zshrc
裡面:
1
2 alias set-company-git-ssh='export GIT_SSH_COMMAND="ssh -i ~/.ssh/COMPANY_KEY";
export PS1="${PS1}COMPANY ==> "'
這樣下了
set-company-git-ssh
後就可以安心使用git
,連 zsh 的$PS1
(prompt) 都會變,一目了然。順帶一提,
npm install
自己也會去吃GIT_SSH_COMMAND
,很方便。
使用情境
工作上需要用公司的 email 申請一個新的 Github 帳號,這樣一來我的系統上就有兩個 Github 帳號用於開發…orz,總之今天摸索了一下多重 SSH key / GitHub 帳號時的應對方式。
需求
- 透過 SSH 而不是 HTTPS 來
clone
/fetch
/push
(這樣就不需要每次 push 都輸入 GitHub 帳號密碼) - 兩個帳號:
- 平常自己用的 GitHub 帳號
- 公司用的 Github 帳號 (以下假設為 `YOU@COMPANY.com`)
- 在 clone 時就決定用哪個帳號來
clone
。 - 以後
git push
時,根據clone
時選的帳號,來自動選擇正確的 SSH key。
協定 長怎樣 需要 Github 密碼 SSH `git@github.com:USERNAME/REPONAME.git` 不用 HTTPS https://github.com/USERNAME/REPONAME.git
每次 push 都要
1. 建立新的 SSH key 並綁定該 Key 給 Github 帳號
因為現在一組 SSH key 只能綁一個 Github 帳號(就算可以綁多個我也不太建議,你會很混亂),所以我們要建立一個新的:
這個很少會做,很多細節都忘光了,所以還是寫一下筆記。
cd ~/.ssh
ssh-keygen -t rsa -b 4096 -C "YOU@COMPANY.com"
這裡假設建立了一個叫 COMPANY
的 SSH key。做完後,這會在 ~/.ssh/
下產生兩個新的檔案。 .pub
結尾的是 public key,另一個則是 private key。
這時打開 Github web 界面中的帳號設定,選 SSH key 那一頁,然後把 public key 整個檔案的內容 copy 下來貼進去。
- 給不知道非對稱加密 的基本概念的人:public key 是公開給別人看的,private key 則是打死不能給任何人看的,不要搞錯了。我遇過很有趣的一次是對方把他的 private key 貼給我了…
- 給不知道 Passphrase 是什麼東西的人:passphrase 跟 Github 密碼毫無關係,這只是讓 private key 多一層保障。在建立 SSH key 時如果有指定 passphrase,以後就算有人拿到你的 private key 檔案也沒辦法用他。缺點是會導致每次 push 都要輸入 passphrase(雖然是不用輸入 Github 的帳號密碼了)。
2. 設定 Bash/Zsh alias 方便 clone
為了以後方便選用不同帳號 git clone 在 ~/.zshrc
或 ~/.bashrc
內加入:
alias company-git-clone='git clone --config user.name="YOUR NAME" --config user.email=YOU@COMPANY.com $@'
以後就只要輸入 company-git-clone REPO-SSH-URL
,效果就等同於:
git clone REPO-SSH-URL
cd REPO
git config user.name "YOUR NAME"
git config user.email YOU@COMPANY.com.tw
注意!其實這部份跟 SSH key 之間並沒有關聯。設定 user.name 跟 user.email 其實就只是以後你在該 repository 下 commit 時,會在 commit log 中顯示的名子跟電子郵件而已。所以當然,(如果公司沒有特別規定的話)你也可以在這裡填自己常用的 email 而不是公司的 email。
你可能會記得,你生平第一次使用 git 前應該有設定過類似這樣的東西:
$ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com
這裡因為有用
--global
,所以這是寫入到你的家目錄下~/.gitconfig
設定檔中。如果不加--global
參數,就變成寫入目前$PWD
所在的 git repository 的.git/config
設定檔中。
現在你應該能夠明白上面這個 alias 在幹麻。總之就是如果repo/.git/config
沒有特別指定 user,就會直接用~/.gitconfig
裡的。
3. 建立 ~/.ssh/config
現在建立 ~/.ssh/config
這個檔案,加入如下內容
#自己私人用的 GitHub 帳號,id_rsa 就是我自己原本用的 ssh key
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
#公司工作用的 GitHub 帳號,此處的 COMPANY 你可以自行取名
Host github.com-COMPANY
HostName github.com
User git
IdentityFile ~/.ssh/COMPANY
4. 如何使用?
拿我的一個小玩具 repo kuanyui/takahashi.js 當作例子:
指令 | 用了 ~/.ssh/ 下的哪個 key |
會用哪個 git user (commit log 顯示哪組 name/email) | |
---|---|---|---|
V |
git clone git@github.com:kuanyui/takahashi.js.git |
id_rsa |
~/.gitconfig 內的設定 |
company-git-clone git@github.com:kuanyui/takahashi.js.git |
id_rsa |
takahashi.js/.git/config 內的設定 |
|
git clone git@github-COMPANY.com:kuanyui/takahashi.js.git |
COMPANY |
~/.gitconfig 內的設定 |
|
V |
company-git-clone git@github-COMPANY.com:kuanyui/takahashi.js.git |
COMPANY |
takahashi.js/.git/config 內的設定 |
我們要用的就是打 V
的那兩個。
只要用這種方法,以後 push 時 git 就會自動選擇要用哪個 ssh key、push 到哪個 GitHub 帳號了。
你可以試著做上面的動作,仔細觀察每次
clone REPO
下來後,REPO/.git/config
的內容差異,一旦了解它們是差在哪,你就會很難忘記這些概念了。