梯子实验室tizilab.net

梯子开了git clone还是慢:给Git和终端设代理

简短回答

梯子开着 GitHub 网页正常、git clone 却慢,常见原因是 Git 和终端不读系统代理,连接直接出了本机。给 Git 设 http.proxy,给终端设 https_proxy 等变量,两处都填梯子客户端在本机开的端口,HTTPS 地址的仓库就会经梯子下载。git@ 开头的 SSH 地址不受这两项影响,要另外给 SSH 配 ProxyCommand,或改用 HTTPS 地址。

背景:这个问题从哪来

情况通常是这样的。梯子客户端开着系统代理,浏览器里 GitHub 的仓库页一秒就出来,回到终端执行 git clone,进度条停在几十 KB/s,或者等一会儿报 Connection timed out。换 npm install、curl 下载安装脚本,现象一样。

系统代理的做法是在系统里登记一个本地地址,比如 127.0.0.1 的某个端口,浏览器会去读,命令行工具大多不读。Git 的官方文档讲代理时只提了两种来源,一是 http.proxy 这类配置项,二是 http_proxy、https_proxy、all_proxy 环境变量,没有提系统代理设置。我们的判断是,终端里的 Git 在没做额外设置时会直接连 GitHub,走的是本地宽带的国际出口,所以才会慢。两种接管方式的差别在 TUN 模式是什么意思 里有对照表。

先找到梯子客户端的本地端口

后面所有设置都要填同一个地址,格式是 http://127.0.0.1:端口号。端口号在客户端的设置页里,名字常叫混合端口、代理端口或 mixed-port。

客户端 本站记录的默认端口 在哪看
Clash Verge Rev 7897 设置页“端口设置”
Clash Party 7890 设置页的混合端口
Clash for Windows 7890 主页第一行

改过端口的,以客户端界面显示为准。下文示例统一写 7897,照着做时换成自己的数字。其他客户端的端口入口可以在 Windows 梯子软件合集 和 Mac 梯子软件合集 里按名字找到对应页面。

给 Git 设代理

全局设置。 在终端执行下面一行,之后所有 HTTPS 地址的仓库都经这个端口:

git config --global http.proxy http://127.0.0.1:7897

git-config 文档写明,http.proxy 会覆盖 http_proxy、https_proxy、all_proxy 这几个环境变量,语法和 curl 相同,所以 socks5:// 开头的地址也能填。要撤掉时执行 git config --global --unset http.proxy。

只给 GitHub 设。 公司或学校有自己的 Git 服务器时,全局代理可能把内网地址也送出去。文档里 http..* 这一节说明,任何 http.* 选项都可以只对匹配的网址生效:

git config --global http.https://github.com.proxy http://127.0.0.1:7897

只给某个仓库设。 在仓库目录里用 remote..proxy,例如 git config remote.origin.proxy http://127.0.0.1:7897。文档写明,这一项设成空字符串就是对这个 remote 关掉代理。

终端代理:给 curl 这类工具设环境变量

curl 读的是环境变量,很多安装脚本内部也调用 curl 下载。只想让当前这个终端窗口走梯子,按系统选一种写法:

终端 写法 生效范围
macOS、Linux 的 bash 或 zsh export https_proxy=http://127.0.0.1:7897 http_proxy=http://127.0.0.1:7897 当前窗口
Windows PowerShell $env:HTTPS_PROXY="http://127.0.0.1:7897" 当前窗口
Windows 命令提示符 set HTTPS_PROXY=http://127.0.0.1:7897 当前窗口

两处细节容易踩到。第一,curl 的文档说明 http_proxy 只认小写,大写的 HTTP_PROXY 不生效,原因和 CGI 协议有关;其他几个变量大小写都认。所以在 macOS、Linux 上建议统一写小写。第二,Microsoft Learn 的说明里写到,Windows PowerShell 5.1 把 curl 定义成了 Invoke-WebRequest 的别名,要用系统自带的 curl 得敲 curl.exe,PowerShell 7 没有这个别名。

npm、pip 这类包管理器还有各自的代理配置项(npm 叫 proxy 和 https-proxy),它们和环境变量谁优先,本文没有列出官方来源,设之前请看各自的文档。

不想走代理的地址写进 NO_PROXY,多个用逗号隔开。curl 手册说明这个变量对 -x 指定的代理同样有效。

git@ 开头的 SSH 地址怎么走代理

复制仓库地址时选了 SSH,得到的是 git@github.com:用户名/仓库.git。这种地址由 ssh 程序连 22 端口,上面的 http.proxy 和 https_proxy 都管不到它。有两个办法。

  1. 改用 HTTPS 地址。 执行 git remote set-url origin https://github.com/用户名/仓库.git,之后就吃到 http.proxy 的设置。推送时要用令牌或凭据管理器登录。
  2. 给 SSH 配 ProxyCommand。 在 ~/.ssh/config 里给 github.com 加一段,让 ssh 经本地端口转出去。常见写法是 ProxyCommand nc -X 5 -x 127.0.0.1:7897 %h %p,这是 OpenBSD 版 nc 的参数;Windows 上常见的做法是换成 Git for Windows 附带的 connect 程序。nc 有好几个版本,参数互不通用,这几种写法本文没有列出官方来源,本站也没有逐个系统核对,用之前先看本机 nc 或 connect 的帮助。

只想临时试一次,不改配置文件,可以用 Git 文档里的 GIT_SSH_COMMAND 环境变量,把 ssh -o ProxyCommand=... 整条命令传进去。长期使用则写进 core.sshCommand。

自己怎么验证

  1. 看 Git 读到了什么。 执行 git config --global --get http.proxy,能打印出地址说明设进去了。看不到就检查是不是设在了仓库级而不是全局。
  2. 看连接实际去了哪。 macOS、Linux 上执行 GIT_TRACE_CURL=1 git ls-remote https://github.com/git/git.git,Git 文档说明这个变量会输出完整的 curl 跟踪。输出里出现连接 127.0.0.1 的那一行,说明请求交给了梯子。
  3. 看客户端日志。 打开客户端的连接或日志页,重新 clone 一次,应当能看到 github.com 的连接,以及它被规则分到了哪个节点。分到直连的话,是规则的问题,排查思路在 规则模式怎么决定一条连接的去向。
  4. 单独测 curl。 执行 curl -I https://github.com,设了环境变量和没设各跑一次,对比返回时间。全部节点都连不上时,先按 节点超时的对照排查 确认梯子本身能用。

这几步只能说明请求有没有进入客户端,速度快慢还取决于节点和线路。本站没有对 git clone 做过留档的测速,上面没有给出速度数字。

这篇没有覆盖的

本文的命令按官方文档整理,本站没有做过留档的实测,Linux 各发行版的 netcat 版本差别也没有逐一核对。永久写入环境变量(bash 的配置文件、Windows 的用户环境变量)、Docker 容器和 WSL 里的代理、npm 和 pip 的配置项、Go 模块代理都没有展开。客户端的默认端口会随版本变化,以客户端界面为准。其他系统的客户端见 梯子下载页。

本文引用的来源5 条 · 在新窗口打开

  1. Git 文档:git-config(http.proxy、http.<url>.*、remote.<name>.proxy、core.sshCommand)git-scm.com
  2. Git 文档:git(环境变量 GIT_SSH_COMMAND、GIT_TRACE_CURL)git-scm.com
  3. curl 手册:--proxy 与 ENVIRONMENTcurl.se
  4. Everything curl:代理环境变量everything.curl.dev
  5. Microsoft Learn:curl on Windowslearn.microsoft.com

常见问题4 题

开了 TUN 模式还要给 Git 设代理吗

一般不用。TUN 在程序发出连接之后接管,Git 的 HTTPS 和 SSH 连接都会进入客户端内核,再按规则分流。两边同时设也能用,但排查时要记得 Git 里还留着一条 http.proxy,关掉梯子后它会让 clone 直接报连不上代理。

设了代理以后 git clone 报 Failed to connect to 127.0.0.1

说明 Git 已经在用代理,只是本地端口没有程序在听。常见情况是梯子客户端没开、端口号写错,或者换了客户端后端口变了。打开客户端设置页核对端口,或者用 git config --global --unset http.proxy 先删掉这一项。

公司内网的 Git 服务器被代理拦住了怎么办

用 http.<url>.proxy 只给 GitHub 设代理,其他地址保持直连。也可以在那台内网服务器对应的 remote 上把 remote.<name>.proxy 设成空字符串,git-config 文档写明这样会关掉这个 remote 的代理。curl 则把内网域名写进 NO_PROXY。

git 设代理用 socks5 还是 http

两种都行,客户端的混合端口同时接受两种请求。区别在域名解析,curl 手册里 socks5h 表示把主机名交给代理去解析,socks5 则由本机先解析。本机 DNS 解析 github.com 不正常时,用 socks5h 或 http 更稳妥一些。

本文最后一次核对来源是 。软件界面、服务政策和法规会变,发现和现在不一致的地方,请按更正与反馈里的方法告诉我们。