优雅的处理Git多帐号与代理问题

  在工作中,常常会容易遇到一台电脑用多个 Git 账号的场景,比如账号 company 账号是工作用的,而账号 personal 是自己个人用的。 由于 Git 本身并没有多账号的机制,导致我们在默认设置下无法很好的区分哪个仓库使用哪个账号。 同时,在某些众所周知的场景下,我们无法直接访问到 Github 仓库,需要走一层 proxy 来加速我们的代码拉取与推送速度, 本文将使用 SSH config 相对优雅的解决这些问题。

前言

  Git 通常的鉴权方式有两种: HTTPS 与 SSH,前者通常是在需要鉴权的操作时(如git push),弹出(或是在命令行提示)填写用户名与密码的认证,通过后方可继续执行,这种方式不是很方便的同时,也存在一定的安全隐患,目前已经被 Github 弃用;后者 SSH 方式,通过提前配置好的 SSH 密钥来对 Git 做鉴权,不再需要输入用户名密码,是现在更为推荐的鉴权方式。
  如何在 Github 配置 SSH 公钥使用密钥认证,参考:
新增 SSH 密钥到 GitHub 帐户
如何配置 SSH 公钥访问 git 仓库? – CODING 帮助中心

  至于代理,在之前的一篇博客 Using a proxy for ssh connections based on netcat 中,我们曾经使用 SSH config来实现对SSH流量的代理。既然 Git 可以通过 SSH 方式进行连接,自然我们也可以使用这种方式来实现代理。

配置

  在Alliot的电脑中,存在四个不同的Git账号,一个是个人的Coding账号,一个是个人的GitHub账号,还有一个是公司的GitHub账号,以及一个自建的Gitea账号。Coding仓库可以直连,不需要代理;而GitHub由于众所周知的原因需要代理来加速;自建的Gitea仓库则需要通过个人的隧道来连接到内网。以下是Alliot所用的整体示例配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 这里可以 Include 其他路径的 ssh config  
# Include /home/root/.ssh/config

# 这是 Coding的配置
Host e.coding.net
Hostname e.coding.net
User git

# 定义ssh私钥地址
IdentityFile ~/.ssh/coding

# 公共仓库,不需要登录的,我直接使用原域
Host github.com
Hostname ssh.github.com
Port 443
User git
# 定义ssh私钥地址
IdentityFile ~/.ssh/alliot

# 使用nc做proxy转发
ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:7890 %h %p

# 自己个人账号下的私有仓库,我定义Host为alliot.github来区分
Host alliot.github
Hostname ssh.github.com
Port 443
User git
IdentityFile ~/.ssh/alliot
# 使用nc做proxy转发
ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:7890 %h %p

# 公司账号,定义Host为corp.github来区分
Host corp.github
Hostname ssh.github.com
Port 443
User git
IdentityFile ~/.ssh/company
ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:7890 %h %p

# 自建的Git
Host git.local
Hostname 192.168.1.123
User git
IdentitAyFile ~/.ssh/key
ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:7890 %h %p
Port 22
ForwardAgent yes

  根据上面的配置可以看出,我们使用 Host 字段来配置仓库地址的别名,在命令行拉取或克隆仓库时,可以使用自定义的 Host 来区分不同的 SSH 密钥,这样就能实现如下效果:
  当需要使用个人 Github 账号来克隆一个仓库时, 我们可以使用如下命令:

1
git clone git@alliot.github:AlliotTech/AlliotTech.git  

  注意,这里使用 alliot.github 代替了原本的 github.com, 这样所有流量都会代理至本地 7890 端口,并且使用 ~/.ssh/alliot 作为 SSH 密钥来鉴权。

  而当需要使用公司帐号的时候,我们可以使用如下的命令:

1
git clone git@corp.github:AlliotTech/AlliotTech.git  

  使用 corp.github 代替了原本的 github.com, 这样就避免了每次都要切换账号的问题。

  需要注意的是,目前(2022年) Github 的 SSH 连接方式必须按照 Alliot 这里的配置来(参考Enabling SSH connections over HTTPS) ,即:

1
2
3
Hostname ssh.github.com
Port 443
User git

否则可能会遇到类似的错误:

1
2
3
4
Connection closed by UNKNOWN port 65535
致命错误:无法读取远程仓库。

请确认您有正确的访问权限并且仓库存在。

拓展阅读

SSH config file for OpenSSH client