1 场景说明

今日开发遇到一个问题:本机wsl坏掉,密钥清空,所以需要重新向项目仓库添加公钥,且需要连接多git账户,私以为值得记录。

原来只做后端开发,没有前端仓库,因此只需向后端仓库账户添加公钥即可。但由于项目交接,现在前端代码也需要本人拉下来变更,且前端与后端仓库账户不一致,所以需要生成两对密钥并分别向前端后端账户添加公钥

2 生成多对密钥

生成多对密钥很简单,只需要使用ssh-keygen -t rsa -C "xxx@yyy.com",并在其后修改名称即可:

ssh-keygen -t rsa -C "xxx@yyy.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/xxx/.ssh/id_rsa): /c/Users/xxx/.ssh/id_rsa_xxx

其中,xxx@yyy.com是你的邮箱,id_rsa_xxx是你想为特定仓库生成特定密钥对的名称。

但仅仅如此,还不能下拉不同仓库代码,因为git默认只能以第一个创建的密钥对来连接。因此需要代理不同的密钥对。

3 代理密钥对(临时方法)

①先执行ssh-agent bash来启动代理服务(不执行会报Could not open a connection to your authentication agent的错)。
微信截图_20220505213122.png

②再执行ssh-add ~/.ssh/id_rsa_xxx来对id_rsa_xxx添加代理,其中id_rsa_xxx是为xxx仓库生成的私钥。微信截图_20220505213025.png

③两步执行完成后,即可对新仓库账户进行操作,也可继续添加私钥,对其他仓库操作。

注意事项:此方法是一次性的,若将当前bash关掉,则全部失效,需要重新走一遍上面两步。有以脚本形式实现永久性的方法:永久ssh代理,但考虑多仓库代码提交并不是常用场景,因此本人没有尝试这种方法,且不同操作系统的脚本编写方式不同,需要读者自行编写shell脚本(很简单)。

4 配置config(永久方法)

对于不想要每次都ssh-agent代理的懒人来说(比如我,没错,时隔近一个月,我终于受不了每次ssh-agent代理的临时方法了),就需要对git的config文件进行配置。

4.1理解git的用户

git的几个user、email等账户的概念比较复杂,刚刚上手会摸不到头脑。但不理解,又无法很好的懂得git的对应关系,下面我会尽力的将这些概念描述清楚。

local用户
此用户为项目配置,在一个项目文件夹下,可以为当前项目配置下面的name和email。配置之后,使用git向远端推代码的时候,就会显示是"xxx@gmail.com"的"xxx"作出了本次提交。

git config --local user.name "xxx"
git config --local user.email "xxx@gmail.com"

global用户
此用户是全局的配置,如果某个项目文件夹没有配置①中的local,那么就会使用global配置。此时使用git向远端推代码的时候,就会显示是"yyy@gmail.com"的"yyy"作出了本次提交。

git config --global user.name "yyy"
git config --global user.email "yyy@gmail.com"

github账户(此处以github为例,gitee等其他仓库也适用):
此处为密钥对的公钥xxx.pub归属地的账户名(这个用户名困扰了我好一阵( ̄. ̄|| ))。归属地是指存放你公钥的那个账户(一个公钥只能存放于一个账户)。
当测试密钥对的联通性时,会提示此用户名,例如:

$ ssh -T git@github.com
Hi morgan-bo! You've successfully authenticated, but GitHub does not provide shell access.

此处morgan-bo为我的github账户,其中添加了我的xxx.pub公钥,当我ssh -T git@github.com时,就会提示此用户名。
如果我换了一对密钥来进行测试,就会提示yyy.pub公钥的归属账户,如下的Admin(此处如果不理解先往后看,全看完就理解了):

$ ssh -T git@gitee.com
Hi Admin! You've successfully authenticated, but GITEE.COM does not provide shell access.

config文件中的Host后面的名字
这个看完4.2章节自然就懂了。

Host nickname
	HostName github.com
        User xxx
        IdentityFile ~/.ssh/id_rsa_xxx
        IdentitiesOnly=yes

config里的User后面的名字
TODO: 暂时我也不知道干嘛的,后续知道了补充,不过这个完全没影响。

4.2配置方法

经过调研,我发现了一种不需要每次配置ssh-agent,只需要修改git clone处nickname的方法,可以直接拉取和推送不同的仓库。
此处的配置很简单,但理解有点复杂,我边配边讲,尽力讲清楚。

①首先查看.ssh文件夹,这个文件夹大家应该都知道的,是存放密钥对的默认文件夹。查看此文件夹下是否有名为config的文件:
41.png
如果没有,就创建一个:
42.png
然后编辑该文件:

$ vim config

并向其中填入如下配置:

Host nickname1
	HostName github.com
        User xxx
        IdentityFile ~/.ssh/id_rsa_xxx1
        IdentitiesOnly=yes
Host nickname2
	HostName github.com
        User xxx
        IdentityFile ~/.ssh/id_rsa_xxx2
        IdentitiesOnly=yes
Host nickname3
	HostName gitee.com
        User xxx
        IdentityFile ~/.ssh/id_rsa_xxx3
        IdentitiesOnly=yes

填好后就可以以不同连接来联通

②其次来说配置的意义以及使用。

可以看到配置每一条配置都有一个Host nickname,我这里之所以取nickname,是因为它就是随便起的。我们来看使用,当我们想通过id_rsa_xxx1这个私钥来访问对应的一个仓库时,我们只需要把原来的:
git clone git@github.com:morgan-bo/test.git
改为
git clone git@nickname1:morgan-bo/test.git

有nginx经验的人就会发现,它就相当于nginx代理的一个路由;或者说就类似于DNS域名解析。通过配置,git会把nickname1解析为其配置中的HostName: github.com

此时,同理,当使用:
git clone git@nickname3:somewhere/test.git
时,就会从gitee.com的test仓库拉取代码。

如果再不理解,可以看这里的测试:

$ ssh -T git@nickname1
$ ssh -T git@nickname2
$ ssh -T git@nickname3

结合得到的结果,就会好理解得多了!此处贴出我的结果,三处仓库对应了三个不同的账户以及三对密钥:
43.png

可以看到,以后想使用不同密钥拉取代码,只需要将url的nickname那一段改成你配置nickname,即可方便的拉取代码啦!

参考文献

[1][ssh-agnet详解](https://blog.csdn.net/zhouguoqionghai/article/details/92134462)
[2][ssh-add报错处理](https://blog.csdn.net/argleary/article/details/100638560)
[3][ssh-agnet用法补充](https://www.cnblogs.com/f-ck-need-u/p/10484531.html)
[4][git多套密钥配置(无ssh-agent,会报错)](https://blog.csdn.net/Justnow_/article/details/54929136)

Q.E.D.


遇事不决,可问春风