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 yes
和IdentityFile
谨慎自称只是一个人。也就是说,稍微更新一下您的部分:
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 仍会尝试多个密钥,无论顺序如何。)
我在 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正在尝试再次使用我的业务回购凭据。
我在 $ ssh-add -D
重启后会使 Git 尊重每个 repo 的 SSH 密钥。但是随后的 macos 重新启动会使问题再次出现。
所以...问题是,为什么 Git 被固定到重启后使用的第一个 SSH 凭据,为什么使用 $ ssh-add -D
清除 SSH 身份可以解决问题,以及如何我改进了我的设置,所以我不必在重新启动后执行解决方法?
TL;DR
使用IdentitiesOnly yes
和IdentityFile
谨慎自称只是一个人。也就是说,稍微更新一下您的部分:
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 仍会尝试多个密钥,无论顺序如何。)