今天在开发的时候遇到一个很离谱的问题,git push 明明昨天还好好的,结果今天突然完全推不上去。
报错信息如下:
vbnet
ERROR: no healthy upstream
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
或者是
vbnet
ERROR: upstream connect error or disconnect/reset before headers.
remote connection failure, transport failure reason: delayed connect error: Connection refused
fatal: Could not read from remote repository.
一开始我以为是 GitHub 挂了,或者我 SSH key 失效了。结果一切正常:
vbnet
ssh -T git@github.com
Hi shenlu89! You've successfully authenticated, but GitHub does not provide shell access.
我又查了一下远端Git仓库的URL是否正确:
scss
git remote -v
origin git@github.com:shenlu89/docs.git (fetch)
origin git@github.com:shenlu89/docs.git (push)
SSH 连接没有问题
- 仓库地址没错
- SSH 授权正常
- git remote -v 正常
那问题从哪里来?
正常来说,使用 SSH 方式 push,那只要 ssh -T 可用,push 一定可用,但我这里:
java
ssh -T git@github.com // 正常
git push // 失败
这说明 push 底层不是简单的 SSH 问题,而是 连接被代理或网络干扰了。
继续排查 macOS 系统代理:
arduino
networksetup -getwebproxy "Wi-Fi"
networksetup -getsocksfirewallproxy "Wi-Fi"
结果是:
yaml
Enabled: Yes
Server: 127.0.0.1
Port: 7890
也就是说,macOS 系统级 HTTP/HTTPS/SOCKS 都指向了 127.0.0.1:7890。
这就导致所有 Git 连接走系统代理,系统代理为空,请求被直接拒绝,Git push 报 connection refused
这就是为什么 SSH 测试能连,但 git push 反而失败。
因为 SSH 测试命令不走系统代理,而 Git push 走了。
直接关掉 macOS 的代理即可:
vbnet
networksetup -setwebproxystate "Wi-Fi" off
networksetup -setsecurewebproxystate "Wi-Fi" off
networksetup -setsocksfirewallproxystate "Wi-Fi" off
然后:
perl
git push
瞬间恢复正常。
还有一种方法,就是将 GitHub SSH 改用 443 端口,为了兼容各种奇怪网络环境(公司、学校、酒店 WiFi 等),我顺手也把 GitHub SSH 通道改到了 443 端口,编辑 ~/.ssh/config:
bash
Host github.com
HostName ssh.github.com
Port 443
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
443 端口一般不会被封,也不受代理影响,比 22 端口稳定太多。
这样问题就成功解决了。