Select 配置取决于远程 url

Select configuration depending on remote url

我在同一台主机上有两种类型的存储库,它们的起始远程不同url:

github.com/foo/bar.git
github.com/foo/foo.git

github.com/bar/bar.git
github.com/bar/foo.git

并且我希望 git 根据当前远程 url 自动 select 身份和 ssh 密钥。这甚至可能吗?

ssh 身份选择有点复杂,但有几种方法可以完成这项工作。最简单的是:你不是基于真正的GitHubURL,而是基于某种 URL:

ssh://gh-id1/user1/repo.git

对比:

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-id1gh-id2(您选择实际的主机名,这些只是示例)。当 ssh 收到这个请求时,ssh 读取它自己的配置文件并说:啊哈,你不是真的想要 gh-id1,你真的想要 git@github.com.

git@部分来自~/.ssh/config中的User行,可选。如果不在.ssh/config文件中使用,则必须将GitURL设置为ssh://git@gh-id1.

IdentityFile 行告诉 ssh 向 github.com 提供哪个密钥。 IdentitiesOnly 行告诉 ssh 不要尝试 other 键。这样你就可以保证只尝试 IdentityFile 行中列出的键。 GitHub根据你是哪个key决定你是你(Fred Flintstone)、你的妻子(Wilma Flintstone)、你的邻居Barney等向他们展示,而不是你的真实身份,因此通过控制你向他们展示的密钥,你可以确保你被识别为你想要声称的那个人。

请注意 Git 在整个过程中 的唯一作用 是 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/foogithub.com/bar 部分来执行此操作,您可以将上述技巧与 Git' s insteadOf 这样您就不必以任何方式更改 存储的 URLinsteadOf 替换技巧在 the git config documentation:

中有描述

url.<em>base</em>.insteadOf
      Any URL that starts with this value will be rewritten to start, instead, with base. In cases where some site serves a large number of repositories, and serves them with multiple access methods, and some users need to use different access methods, this feature allows people to specify any of the equivalent URLs and have Git automatically rewrite the URL to the best alternative for the particular user, even for a never-before-seen repository on the site. When more than one insteadOf strings match a given URL, the longest match is used.

所以在这里你可以写:

git config --global url.ssh://gh-user1/foo/.insteadOf ssh://github.com/foo/

ssh://github.com/foo/repo.git 转换为 ssh://gh-user1/foo/repo.git。另请参阅 and 了解相关(但不同)示例。

如果这还不够

如果出于某种原因您需要 非常复杂 ssh URLs 操作,您可以将 Git 指向 运行,而不是系统 ssh 命令,而不是任何 Git-for-Windows 提供的 ssh 命令,而是您自己的 custom-made ssh 程序。这个程序 可以用它的参数 做任何你喜欢的事情,只要它最终实现或 运行ning 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 的默认程序 built-in ssh.

(要控制您在此处提供的密钥,请考虑使用 ssh-i 选项。)

首先感谢@torek 的精彩回答。

我注意到我也可以只使用共享 ssh-key。例如,如果您像我一样使用 JetBrains Space,您只需为每个工作区上传一次 ssh-key。 URL 并不重要,Space-Server 决定使用哪个帐户。

这就是我个人现在采用的解决方案。