深入探讨git与ssh config (多个git账户配置与连接)

本文最后更新于:2024年4月10日 下午

背景

在使用Git和GitHub / Gitlab进行项目管理和代码托管时,开发者可能会遇到需要同时管理多个GitHub账户的情况。这种需求可能源于个人和工作项目之间的区分,或者参与多个组织的开发工作。然而,Git和SSH的默认配置并不直接支持轻松切换多个账户,这就需要一些额外的配置和策略来解决。

对于笔者,同时需要连接到github和gitlab,于是在ssh下面的config文件进行了配置。

问题起源

在进行github连接的时候,首先在~/.ssh/config配置了如下内容:

1
2
3
4
Host github
HostName github.com
User git
IdentityFile abc (a private key)

运行情况:

  1. ssh -T github, 成功
  2. ssh -T git@github.com,成功
  3. git clone git@github.com:myusername/repo.git (这个仓库是一个私有仓库),失败。报错信息:
1
2
git@github.com: Permission denied (publickey).fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists
  1. 将.ssh/configHost改为github.com, 情况3成功

原因

Host github定义了一个SSH配置的别名github,这意味着当你使用SSH或Git命令与GitHub通信时,可以使用这个别名来引用整个配置块。即别名Host = HostName + User + IdentifyFile。

基于这个原因,我们就理解了下面的图:

image-20240410125934423

直接通过ssh连接的时候,SSH可以通过Host找到HostName,也可以根据HostName找到同级下面的key,所以成功。

但是,

在使用git clone命令时,如果直接使用git@github.com:USER/REPOSITORY.git这样的URL,相当于提供了完整主机名,Git客户端内部会调用SSH客户端(而且用户名都是git),此时SSH客户端,也会根据~/.ssh/config中的配置来尝试解析主机名github.com。如果找不到有关github.com的配置,就会报错。此时不会根据github.com找到同级的identify Key。

其实是合理的,因为如果像下面这样,有两个github账户,那么一个别名1,一个别名2,也无法找到需要哪个key,也就无法决定使用哪个账户clone。

1
2
3
4
5
6
7
8
9
10
# github1
Host github1
HostName github.com
User git
IdentityFile abc
# github2
Host github2
HostName github.com
User git
IdentityFile def

所以必须手动提供这个别名,也就是必须改为git@github:USER/REPO.git。 这样的话,git里的ssh就可以从上到下找到正确的key

问题回溯

谈到这里,我们就会发现,情况3失败是正常的,因为可能有多个github账户,于是现在问题变成了,情况2为什么可以?

ssh -vT git@github.com,查看debug输出,发现其实这样能成功,无非是ssh把我本地的两个key都尝试提供了,然后第二个key刚好能连上。。。

image-20240410132928617

甚至进一步ssh -vT git@github,发现也会同时尝试两个key,只不过是优先使用匹配到的key连接。

结论

  1. 别名 == 下面的所有配置块总和
  2. 当通过 ssh 直接连接的时候,优先查看是否匹配到了config文件中的某一行
    1. 如果在config文件中找不到,会尝试本地所有的key
    2. (注意) 即使在config文件中找到,也会尝试所有key,但是优先尝试匹配到的key (体现了ssh客户端本身的兼容性
  3. 当通过 git 调用 ssh 的时候,由于git权限更加严格,因此不会尝试所有的key,而是严格匹配config文件。所以使用git连接多个账户时,无法使用标准URL,而是必须替换为别名。
  4. 另外git还有个gitconfig文件,允许使用从Github仓库页面复制的标准url。可以免去把 github.com 改为自定义主机名的麻烦。

TODO

或许之后再研究下gitconfig

参考

  1. https://gist.github.com/oanhnn/80a89405ab9023894df7
  2. https://zian999.github.io/zh/posts/2020/20200122-generate_ssh_key_and_ssh_config/

深入探讨git与ssh config (多个git账户配置与连接)
https://blogoasis.github.io/post/800844d7.html
作者
phInTJ
发布于
2024年4月10日
许可协议