深入探讨git与ssh config (多个git账户配置与连接)
本文最后更新于:2024年4月10日 下午
背景
在使用Git和GitHub / Gitlab进行项目管理和代码托管时,开发者可能会遇到需要同时管理多个GitHub账户的情况。这种需求可能源于个人和工作项目之间的区分,或者参与多个组织的开发工作。然而,Git和SSH的默认配置并不直接支持轻松切换多个账户,这就需要一些额外的配置和策略来解决。
对于笔者,同时需要连接到github和gitlab,于是在ssh下面的config文件进行了配置。
问题起源
在进行github连接的时候,首先在~/.ssh/config
配置了如下内容:
1 |
|
运行情况:
ssh -T github
, 成功ssh -T git@github.com
,成功git clone git@github.com:myusername/repo.git
(这个仓库是一个私有仓库),失败。报错信息:
1 |
|
- 将.ssh/configHost改为
github.com
, 情况3成功
原因
Host github
定义了一个SSH配置的别名github
,这意味着当你使用SSH或Git命令与GitHub通信时,可以使用这个别名来引用整个配置块。即别名Host = HostName + User + IdentifyFile。
基于这个原因,我们就理解了下面的图:
当直接通过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 |
|
所以必须手动提供这个别名,也就是必须改为git@github:USER/REPO.git
。 这样的话,git里的ssh就可以从上到下找到正确的key
问题回溯
谈到这里,我们就会发现,情况3失败是正常的,因为可能有多个github账户,于是现在问题变成了,情况2为什么可以?
ssh -vT git@github.com
,查看debug输出,发现其实这样能成功,无非是ssh把我本地的两个key都尝试提供了,然后第二个key刚好能连上。。。
甚至进一步ssh -vT git@github
,发现也会同时尝试两个key,只不过是优先使用匹配到的key连接。
结论
- 别名 == 下面的所有配置块总和
- 当通过 ssh 直接连接的时候,优先查看是否匹配到了config文件中的某一行
- 如果在config文件中找不到,会尝试本地所有的key
- (注意) 即使在config文件中找到,也会尝试所有key,但是优先尝试匹配到的key (体现了ssh客户端本身的兼容性
- 当通过 git 调用 ssh 的时候,由于git权限更加严格,因此不会尝试所有的key,而是严格匹配config文件。所以使用git连接多个账户时,无法使用标准URL,而是必须替换为别名。
- 另外git还有个
gitconfig
文件,允许使用从Github仓库页面复制的标准url。可以免去把 github.com 改为自定义主机名的麻烦。
TODO
或许之后再研究下gitconfig