我在同一主机上有两种类型的存储库,它们的起始远程url不同:
github.com/foo/bar.git
github.com/foo/foo.git
github.com/bar/bar.git
github.com/bar/foo.git
我希望git根据当前的远程url自动选择标识和ssh密钥。这可能吗?
ssh身份选择有点复杂,但有几种方法可以实现这一点。最简单的方法是:你不基于真实的GitHubURL,而是基于一种伪造的URL:
ssh://gh-id1/user1/repo.git
vs:
ssh://gh-id2/user2/repo.git
在ssh配置文件中,您可以编写,例如:
Host gh-id1
Hostname github.com
User git
IdentityFile ~/.ssh/id-user1.rsa.pub
IdentitiesOnly yes
Host gh-id2
Hostname github.com
User git
IdentityFile ~/.ssh/id-user2.rsa.pub
IdentitiesOnly yes
这里的概念是Git要求ssh连接到伪造的主机名gh-id1
或gh-id2
(您可以选择实际的主机名,这些只是示例)。当ssh收到这个请求时,ssh读取它自己的配置文件并说:Aha,你不是真的想要gh-id1
,你确实想要git@github.com
git@
部分来自~/.ssh/config
中的User
行,这是可选的。如果不在.ssh/config
文件中使用它,则必须将Git URL设置为ssh://git@gh-id1
。
IdentityFile
行告诉ssh向github.com
提供哪个密钥。IdentitiesOnly
行告诉ssh不要尝试其他密钥。这样,您就可以保证只尝试IdentityFile
行中列出的密钥。GitHub决定你是你(Fred Flintstone)、你的妻子(Wilma Flintstone
请注意,Git在整个过程中的唯一作用是让ssh连接到你编造的、你控制的、在.ssh/config
文件中列出的一些伪造的主机名。Git本身在这里不进行任何身份验证:它将整个工作押在ssh上。
您可以使用insteadOf
触发此
为了实现上述功能,您通常会将某个存储库的存储的URL设置为ssh://gh-id1/user1/repo.git
。您可以使用git remote set-url origin ssh://gh-id1/user1/repo.git
或通过最初克隆ssh://gh-id1/user1/repo.git
来完成此操作。
请注意,如果你的目标是基于URL的github.com/foo
和github.com/bar
部分来实现这一点,你可以将上述技巧与Git的insteadOf
结合起来,这样你就不必以任何方式更改存储的URL。git config
文档中描述了insteadOf
替换技巧:
url.base.insteadOf
任何以该值开头的URL都将被重写为开始,而使用base
。在某些站点为大型存储库的数量,并通过多重访问为其提供服务方法,并且一些用户需要使用不同的访问方法,这该功能允许用户指定任何等效的URL和让Git自动将URL重写为特定的用户,即使是上从未见过的存储库地点当多个insteadOf
字符串与给定URL匹配时使用最长匹配。
所以你可以在这里写:
git config --global url.ssh://gh-user1/foo/.insteadOf ssh://github.com/foo/
以将CCD_ 27变换为CCD_。有关相关(但不同)示例,请参阅如何将`git:`urls转换为`http:`urls'以及如何将git默认为ssh而不是https。
如果这还不够的话
如果出于某种原因,您需要对ssh URL进行非常复杂的操作,您可以直接运行Git,而不是系统ssh
命令,也不是任何Git for Windows提供的ssh
命令,而是您自己定制的ssh
程序。这个程序可以用它的参数做任何你喜欢的事情,只要它最终实现或运行ssh
。因此,您可以编写一个脚本或程序——让它变得任意愚蠢或智能——找到URL,重写它,然后调用系统ssh。
要做到这一点,首先编写自己的程序并验证它是否有效:
my-fake-ssh ssh://github.com/foo/bar.git
my-fake-ssh git@github.com/foo/bar.git
然后简单地将core.sshCommand
设置为my-fake-ssh
:
git config --global core.sshCommand my-fake-ssh
Git现在将运行您的程序,而不是Git默认的内置ssh。
(要控制此处提供的密钥,请考虑使用ssh
的-i
选项。)
免责声明:这将不会自动选择密钥
对于想要快速移动的懒惰/务实的程序员
- 为每个repo定义不同的ssh密钥
- 在运行git命令之前,请使用以下任一项:
GIT_SSH_COMMAND=";ssh-i~/.ssh/id_for_for_foo_repo">
GIT_ SSH_ COMMAND=";ssh-i~/.ssh/id_for_bar_repo">
我觉得这更简单,我更喜欢精细控制
首先感谢@torek的精彩回答。
我注意到,我也可以只使用共享的ssh密钥。例如,如果您像我一样使用JetBrains Space,那么您只需为每个工作区上传一次ssh密钥。URL并不重要,而是由Space Server决定使用哪个帐户。
这就是我个人现在所采用的解决方案。