问题

使用github过程中,如果有多个github账号,从同一台工作电脑提交时经常会遇到类似下面的权限问题。注意这里提到的问题使用的是github的SSH连接方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git:(main) git push -u origin main
ERROR: Repository not found.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.


git:(main) git pull origin
Connection closed by 198.18.0.138 port 22
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

分析

简单来说这里的问题是代码仓和登录github的账号没有对应起来,造成权限问题。

比如说我们有github账号account1和account2,account2下面有代码仓库repo1。如果我们在repo1本地目录做git操作时,使用的是account1,那么就会大概率遇到这里提到的权限问题。

那么我们从本地拉或者提交github仓库中的代码时,到底使用的是哪一个github账号,github又是怎么验证账号的呢?

如题我们使用的是SSH方式连接github,认证使用的公私钥认证。

一般来说Github上申请一个账号后,我们都会通过ssh-keygen本地生成公私钥后,把公钥上传到GitHub网站。

下面介绍一下认证过程。

  1. 本地git pull或者git push时发起SSH连接过程。SSH客户端把公钥传给GitHub服务端
  2. GitHub服务器收到请求后,从后台数据库中搜索已经注册的公钥列表,找到后说明该用户存在。那怎么证明这个客户端用户拥有这个公钥呢?服务端会生成一个随机数并用公钥加密发送回客户端
  3. 客户端收到返回的消息后用私钥解密(只有拥有私钥的客户端才能解密),并把解密的随机数再发到服务端
  4. 服务端通过解密的随机数验证合法的SSH客户端,也就是这里的github账户

所以,Github服务端是通过不同公钥证书来区分不同GitHub账号的。

那多个github账户从同一台客户端电脑比如Mac操作时使用的到底是哪一个账号或者说证书呢?

遗憾的是没有简单的方法。但是我们可以通过执行下面的命令从结果来判断当前使用的github账户名。shidongwa是当前使用的github账户。

1
2
3
git:(main) ssh -T git@github.com
Hi shidongwa! You've successfully authenticated, but GitHub does not provide shell access.

那如何切换到第二个github账号呢?

有。其实只要连接Github服务端时支持切换到第二个公私钥对即可。这个可以借助SSH客户端的多账户认证来实现。

简单来说就是在~/.ssh/configSSH配置文件中指定不同服务器别名,关联不同的私钥。代码仓库中remote url中使用服务器别名即可。

具体步骤如下:

  1. 在本地,不同账号生成不同的公私钥对,也就是文件名。Mac下命令:ssh-keygen -t ed25519 -C "XXX@gmail.com",主要提示Enter file in which to save the key (/Users/XXX/.ssh/id_ed25519)需要输入完整文件路径,也就是存放公私钥文件位置的地方
  2. 把生成的公钥证书文件上传GitHub。这个是Github账号维度,不是项目维度。你需要使用你操作的目标代码仓库对应的GitHub账号登录GitHub后才能配置公钥文件
  3. 配置本地SSH客户端,不同github服务器别名关联不同ssh证书。这里假定第二步生成的私钥文件地址分别是~/.ssh/id_ed25519_account1~/.ssh/id_ed25519_account2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 个人账户的配置
Host github.com-account1
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_account1
IdentitiesOnly yes

# 工作账户的配置
Host github.com.account2
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_account2
IdentitiesOnly yes

  1. 本地代码仓库更新远程仓库地址,使用第三步配置的github服务器别名。注意下面命令中的account1account2是你的github账户名
1
2
3
4
5
# 使用account1
git remote set-url origin git@github.com.account1:account1/XXX.git

#使用account2
git remote set-url origin git@github.com.account2:account2/XXX.git
  1. 现在可以正常使用git pull或者git push了。可以通过下面命令来验证连通性。注意下面命令中的account1需要替换为你的github账号
1
2
ssh -T git@github.com.account1
Hi account1! You've successfully authenticated, but GitHub does not provide shell access.

一般来说为了从git log中直观看出不同账号的提交记录。可以在代码仓库本地维度配置user.nameuser.email

1
2
git config user.name "acocunt1"
git config user.email "account1@gmail.com"

总结

同一台工作电脑上多个github账号提交代码可以通过SSH客户端多账号配置来支持,简单来说就是git通过告诉SSH客户端使用不同github服务器别名,不同SSH公私钥对来区分不同github账号。和单账号操作相比,主要区别在上面操作步骤中的第3步和第4步。

如果不使用本文提到的SSH多账户认证方式,也可以通过不同Github账户增加代码协作者来临时解决,也就是account2 github仓库允许account1用户提交代码。不过这种方式不一定满足业务要求。