Git 和 Gitlab/Github 多账号

在工作中经常会遇到 Git 多账号的场景,例如:

  • GitHub 和 GitLab 仓库使用不同账号
  • 公司仓库和个人仓库使用不同账号
  • 个人私有仓库和个人开源仓库使用不同账号

那在 Git 当中如何管理多账号呢?首先要明确以下概念:

Git 账号和 GitHub/GitLab 账号不是一回事

下图说得很明白,Git 是高质量的版本控制系统,GitHub 是云端代码托管平台:

git_vs_github

Git 账号

在 Git 中其实是不存在账号的概念的,即没有登录、鉴权等步骤,只有一个全局和本地的配置,能够设置 user.name 和 user.email 用于标识提交者信息。假如说你刚安装 Git,首次提交代码的时候会有如下提示:

1
2
3
4
5
6
7
8
9
10
11
12
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

git config --global user.name "Your Name"
git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

git commit --amend --reset-author

1 file changed, 1 insertion(+)

就是说你还没有设置提交人信息,全局和项目都没有设置,全局的配置在文件:~/.gitconfig 中,项目设置在 .git/config 中,如果都没有的话,Git 就会获取操作系统用户信息作为提交人信息,例如在 Mac 中,获取方式为 用户全名 <用户名@主机名>,其中:

  • 用户全名用 id -F 获取
  • 用户名用 id -un 获取
  • 主机名用 hostname 获取

所以,如果你不设置提交人信息的话,电脑信息就暴露了,所以建议大家根据上面的提示进行设置。

GitHub/GitLab 账号

这两个账号不用说了,就是登录网站注册得到的,但是注册之后有一个很重要的步骤就是配置 SSH Key,如果不配置的话,网站无法对提交人进行鉴权,因此就无法提交到仓库中。首先要在电脑上生成 SSH Key,生成方法很简单:

1
ssh-keygen -t rsa -C "xxxxx"

运行之后,在 ~/.ssh 目录下会多出两个文件:

1
2
-rw-------@ 1 keliq  staff   1.6K 12 16  2015 id_rsa
-rw-r--r--@ 1 keliq staff 416B 12 16 2015 id_rsa.pub

其中 id_rsa.pub 就是公钥,通过 cat ~/.ssh/id_rsa.pub 获取其内容,复制到 GitHub 或 GitLab 账户的 SSH Key 里面即可,下次再提交的话就能通过了。

ssh-key

Git 多账号和 GitHub/GitLab 多账号操作步骤

Git 多账号

在一个项目中,用下面的命令修改用户名和邮箱即可:

1
2
git config user.name xxx
git config user.email xxx

这样的话,就相当于设置了一个新的 Git 账号了,但是要注意,这里的邮箱比较重要,在提交到 GitHub/GitLab 网站的时候,会根据这里设置邮箱(即 user.email)与 GitHub/GitLab 账号中的邮箱进行匹配,如果匹配上了,commit 中的用户名和头像就会 GitHub/GitLab 账号的用户名和头像,如果没匹配上,commit 中的用户名就用 user.name,然后头像没了!头像没了!头像没了!重要的事情说三遍。

GitHub/GitLab 多账号

这才是本文的重点,如何给托管平台 GitHub/GitLab 配置多账号。上面已经知道代码托管平台实际上是通过 ~/.ssh/id_rsa.pub 来认证用户的,所以只要多生成几个密钥对就相当于生成了多个托管平台的账号了!注意,生成密钥对之后,记得添加到 GitHub 或 GitLab 账户的 SSH Key 里面。

但是生成密钥对的时候不要覆盖之前的密钥对,因为默认会保存到同样的位置,即 ~/.ssh/id_rsa,如果没备份的话,千万不要覆盖,不然就找不到了!(真覆盖了话,也不是什么大事,把原 SSH Key 从托管平台里面删了即可),例如你可以先保存到当前目录下,然后移动到其他位置,例如 ~/.ssh/keliq/ 目录:

1
2
3
4
5
6
7
ssh-keygen -t rsa -C "xxx"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/keliq/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub

到这里,你就拥有多个 SSH Key 了,于是可以通过下面的命令切换身份:

1
2
3
4
5
6
# 默认就是用的 ~/.ssh/id_rsa,所以加不加一个效果
GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa" git clone xxxx
# 使用另外一个私钥
GIT_SSH_COMMAND="ssh -i ~/.ssh/keliq/id_rsa" git push
# 使用 gitlab 的私钥,当然你得把对应的公钥添加到 gitlab 的 SSH Key 里面才行
GIT_SSH_COMMAND="ssh -i ~/.ssh/gitlab/id_rsa" git push

这种方式虽然灵活,但是不够智能,例如我想要的效果就是:某个平台的所有仓库都使用某个私钥进行认证,这种需求很常见,打开 ~/git/config 文件配置如下:

1
2
3
4
5
6
7
8
9
Host github.com
User git
Hostname github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/github/id_rsa
Host gitlab.com
Hostname gitlab.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/gitlab/id_rsa

到这里,多账号的配置基本上已经完成了,但是还有一个不足的地方就是虽然私钥根据域名自动选择了,但是提交的配置还是共享 .gitconfig 中的配置,例如 user.name 和 user.email,能不能根据仓库所在的不同位置选择不同的全局配置文件呢? 答案是可以的,打开 ~/.gitconfig 文件,在末尾添加下面的配置:

1
2
[includeIf "gitdir:~/work/gitlab/"]
path = .gitconfig-gitlab

然后再建一个 ~/.gitconfig-gitlab 文件,里面写全局配置,例如:

1
2
3
[user]
name = keliq
email = keliq

那么只要仓库被放到了 ~/work/gitlab 目录下面,默认就会使用这个配置了!