跳到内容
观澜涉川 · 札记EN

在同一台开发机上隔离多个 Git 账号

· 约 2 分钟阅读

同一台开发机上经常会有多个 Git 身份:自己的账号、开源组织的账号,或者不同代码托管平台上的账号。每个身份都有自己的 SSH 密钥,一旦混用,轻则被服务器拒绝,重则把提交推到不该推的账号下。

与其每次手动切换,不如把目录和密钥的对应关系固定下来,让 Git 按路径自动选择。

生成密钥:每个身份一把

先给每套身份生成独立的 Ed25519 密钥,不要复用默认的 id_ed25519:

Terminal window
ssh-keygen -t ed25519 -C "alpha@example.com" -f ~/.ssh/id_ed25519_alpha
  • -t ed25519:推荐的算法,密钥短、签名快,主流平台都支持
  • -f:指定输出路径,避免覆盖已有的默认密钥
  • -C:注释,写清用途,方便在平台上辨认

执行过程中会提示设置 passphrase。建议设置,并把它加入 ssh-agent,免得每次推送都要输入(如果 ssh-agent 尚未运行,先执行 eval "$(ssh-agent -s)"):

Terminal window
ssh-add ~/.ssh/id_ed25519_alpha

接着收紧权限:

Terminal window
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519_alpha
chmod 644 ~/.ssh/id_ed25519_alpha.pub

查看公钥,添加到对应平台或服务器:

Terminal window
cat ~/.ssh/id_ed25519_alpha.pub

私钥(没有 .pub 后缀的那个文件)不要外传,也不要放进同步盘或仓库。另外,同一个公钥不能同时添加到两个 GitHub 账号,每套身份都要单独生成一对。

按目录加载不同配置

前提是不同身份的代码放在不同目录,比如 ~/workspace/alpha/ 和 ~/workspace/beta/。Git 的 includeIf 可以按仓库路径加载不同的配置文件(需要 Git 2.13 及以上)。

在 ~/.gitconfig 末尾加入:

[includeIf "gitdir:~/workspace/alpha/"]
path = ~/.gitconfig-alpha

然后创建 ~/.gitconfig-alpha:

[core]
sshCommand = ssh -i ~/.ssh/id_ed25519_alpha -o IdentitiesOnly=yes

两个细节:

  • gitdir:~/workspace/alpha/ 末尾的 / 不能省,它表示“该目录下的所有仓库”;不带 / 只匹配该路径本身。
  • IdentitiesOnly=yes 让 SSH 只使用 -i 指定的钥匙,不再把 ssh-agent 里的其他密钥逐个递给服务器。没有它,agent 里恰好有另一把被授权的钥匙时,Git 可能以错误的身份通过认证。

之后这个目录下的仓库自动使用 alpha 的密钥,其他地方不受影响。需要几套身份,就重复几组 includeIf 和对应的配置文件。

只对单个仓库生效

如果不想按目录管理,进入仓库后直接设置局部配置:

Terminal window
git config core.sshCommand "ssh -i ~/.ssh/id_ed25519_alpha -o IdentitiesOnly=yes"

这个值会写进该仓库的 .git/config,优先级高于全局配置。

顺带切换提交身份

SSH 密钥决定“以什么身份连接”,user.name 和 user.email 决定“以什么身份提交”,两者要一起改。在 ~/.gitconfig-alpha 里再加一段:

[user]
name = Alpha
email = alpha@example.com

这样该目录下仓库的提交作者也不会串。

验证

在 ~/workspace/alpha/ 下任意仓库里查看配置来源:

Terminal window
git config --show-origin --get core.sshCommand

--show-origin 会显示这条配置来自哪个文件,能确认 includeIf 确实命中了。再验证密钥本身:

Terminal window
ssh -i ~/.ssh/id_ed25519_alpha -o IdentitiesOnly=yes -T git@github.com

这条命令直接调用 ssh,不会读取 Git 的 core.sshCommand,所以要手动带上同样的参数。若要连真实仓库测试:

Terminal window
git ls-remote git@github.com:your-org/your-repo.git

小结

  • 每个身份单独生成一对 Ed25519 密钥,私钥不外传,公钥只加到对应账号。
  • 用 includeIf 按目录加载配置,用 core.sshCommand 指定密钥,并加上 IdentitiesOnly=yes。
  • 密钥之外,别忘了同目录下的 user.name 和 user.email,否则连接身份对了,提交作者还是会串。
  • 临时切换可以只对单个仓库设置 core.sshCommand,不必动全局配置。

参考