Git 多个 SSH macos 设置卡在一个帐户上

Git multiple SSH macos setup stuck on one account

我在 macos 上使用两个 Github SSH 密钥时遇到问题,它卡在重新启动后使用的第一个帐户上。

Background:

我的 mac 设置了两个 Github 帐户 - 一个用于 personal 代表os 仓库,另一个用于 business 回购。商业回购是私有的。个人repo是public,但是只有我的个人账号可以推送。

System setup:

我的系统和全局配置是空的

~/.ssh/config:

# business
Host business
 HostName github.com
 User git
 IdentityFile ~/.ssh/id_rsa 
 UseKeychain yes
 AddKeysToAgent yes

#personal
Host personal
 HostName github.com
 User git
 IdentityFile ~/.ssh/id_rsa_personal
 UseKeychain yes
 AddKeysToAgent yes

personalreporoot/.git/config

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[user]
    name = personalgithubaccount
    email = mypersonalemail@pm.me

[remote "origin"]
    url = git@personal:mygithubuser/personalrepo
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

businessreporoot/.git/config

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[user]
    name = businessgithubaccount
    email = businessemail@businessdomain.com
[remote "origin"]
    url = git@business:businessname/businessrepo
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
    remote = origin
    merge = refs/heads/main

一切正常,直到我重新启动计算机。当我试图推动我的个人代表os时,我注意到了这个问题。错误说企业帐户没有推送到个人仓库的权限。

我花了几个小时浏览 Stack Overflow 和互联网文章,其中 most 建议删除我的 macos 钥匙串 git 条目并删除osxkeychain 来自配置文件,但无济于事。最后,借助 101 故障排除,我重新启动并中提琴,我可以推送到个人帐户,它现在使用我的个人凭据而不是我的企业凭据。

但是——然后我去了 git pull 的商业回购,它说找不到代表os 。弄清楚我遇到了相互问题,它现在卡在我的个人帐户上,我重新启动,提取业务回购并且它工作,但现在我无法推送到我的个人代表os itory,因为git正在尝试再次使用我的业务回购凭据。

我在 that linked to these instructions 中找到了解决方法。似乎 运行 $ ssh-add -D 重启后会使 Git 尊重每个 repo 的 SSH 密钥。但是随后的 macos 重新启动会使问题再次出现。

所以...问题是,为什么 Git 被固定到重启后使用的第一个 SSH 凭据,为什么使用 $ ssh-add -D 清除 SSH 身份可以解决问题,以及如何我改进了我的设置,所以我不必在重新启动后执行解决方法?

TL;DR

使用IdentitiesOnly yesIdentityFile谨慎自称只是一个人。也就是说,稍微更新一下您的部分:

Host business
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa
    IdentitiesOnly yes

然后确保将 URL ssh://business/path/to/work-repo.git 用于工作存储库(或者 business:path/to/repo.git 如果您喜欢简短版本),以及 ssh://personal/path/to/personal-repo.git 用于个人存储库。

So...the questions are, why does Git get pinned to the first SSH credential used after a reboot ...

它不是,真的——这不是真正的 macOS 问题,它在任何 ssh 设置中都是普遍的(尽管细节会有所不同,具体取决于您是否使用 ssh-agent 以及如何使用;macOS 设置您如此all new Terminal windows share 默认情况下一个代理,这通常是你想要的)。理解这一点的诀窍是理解 ssh 密钥的工作原理:ssh 如何向您希望验证的站点提供密钥,以及 GitHub 如何使用这些 ssh 密钥。

首先,让我们定义一个 ssh 密钥。它是:

  • 您使用某些加密算法的字节串;
  • 由 public 和私钥构建。

一般来说,您将私钥保密并出示 public 密钥,或用私钥加密的东西,或用两个密钥加密的东西,或其他任何东西:细节不是很清楚重要的。我们知道(并关心)的是 public 密钥被泄露,而私钥没有,我们可以假装你的“密钥”显示给其他网站(例如 github.com)的是 public 键。

现在,仅仅提供密钥本身并不能证明你是。有人可能在之前的交易中偷偷复制了您的 public 密钥。因此 GitHub(或任何你连接的人)会向你发送一些加密的随机数据,如果你有 private[=,你只能 decrypt 88=] 键。您解密它,从而向 GitHub 证明您不仅拥有您发送给他们的 public 密钥,而且您是相应私钥的持有者。

GitHub,那么,考虑到这两点,现在就知道你是你自称的那个人了。但是你 声称自己是谁? 为什么,谁拥有那把 public 钥匙,谁就是谁。

所以,假设您有 两个 键,这两个键都可以使用。今天,您先出示public键A。他们向您发送挑战,以测试您是否真的是 A 私有一半的持有者,并且您回答正确。好吧,这就解决了:你是 A.

明天,你打电话给他们,先出示 public 键 B。他们给你一个挑战,你正确回应,然后就解决了。你是 B.

你就是你第一次提供的人。因此,就 GitHub 而言,你 的人,就是你第一次声称自己是的人 。 =22=]

但假设在星期六(如果明天是星期五)你提供 public 密钥 A 未能发送正确的响应,然后提供 public 键 B 发送正确的响应 。 GitHub 现在会认为您是 B

所以 GitHub 真的相信你就是你成功声称的那个人。这意味着即使你总是先提供 A撤销你的私钥A 也足以让你成为B。这或多或少就是您的 ssh-add -D 所做的。 (你的 ssh 可能很聪明,如果它没有正确的私钥,它甚至不会提供 public 密钥,因为如果你声称是 A 是没有意义的重新计划挑战失败。当然,任何一种方法都有效,但总的来说,最好不要用一百万次钥匙尝试敲门太多:人或正确编程的计算机会产生怀疑。)

最后,这意味着您必须确保 Git 不会 首先提供 错误的 密钥。使用代理时,您可以添加任意数量的密钥,ssh 将能够“看到”所有这些密钥。它将按某种顺序提供所有 工作密钥对,除非 您使用IdentitiesOnly yes。如果您确实使用此行,它将仅提供有 IdentityFile 行 and/or -i 选项的键。 (请注意,您可以列出多个文件,ssh 仍会尝试多个密钥,无论顺序如何。)