GitHub 访问慢、git clone 卡住、push 超时的完整解决方案
最常见的原因是开了系统代理但 git 没走:git 和 SSH 有自己的一套代理配置,必须单独设置才生效。
先说最常见的一种情况:浏览器打开 GitHub 正常,但 git clone 卡住不动。这几乎一定是因为你开的是「系统代理」,而 git 和 ssh 命令不读系统代理。最快的解决办法是执行一句 git config --global http.proxy http://127.0.0.1:7890(端口换成你客户端里的实际端口),或者直接打开客户端的 TUN 模式。如果是网页本身也很慢,那就是另一类问题,往下看第一节的区分方法。
先分清:是网页慢,还是 git 操作慢?
这两件事的原因几乎没有交集,混在一起排查只会浪费时间。花三十秒做个对照。
| 现象 | 网页打开 | git clone / push | 结论 |
|---|---|---|---|
| A | 正常 | 卡住或超时 | git 没走代理,去配 git 代理 |
| B | 很慢或打不开 | 也很慢 | 整体链路问题,去查节点与延迟 |
| C | 正常 | 正常,但 raw / Release 慢 | 分流规则漏了子域名 |
| D | 正常 | 首次 clone 极慢,后续正常 | 仓库体积问题,用浅克隆 |
| E | 正常 | 只有 push 超时 | 上行带宽或大文件问题 |
对应 A 的情况直接跳到「怎么给 git 单独配代理」;对应 B 的先把基础链路修好,延迟与丢包的排查方法见 网络延迟高、丢包严重怎么办;C、D、E 在后面各有专门一节。
为什么会出现这些差异?
GitHub 不是一个域名,而是一组服务分布在不同域名与不同基础设施上:网页在一套 CDN 上,git 的数据传输走另一条路径,raw 文件和 Release 附件又各自托管在对象存储上。再叠加上 git 自身独立于系统的网络配置,就出现了「这个能用那个不能用」的错位感。
| 出问题的环节 | 典型表现 | 背后原因 | 解决方向 |
|---|---|---|---|
| git 的 HTTPS 传输 | clone 卡在 0%,长时间无输出 | git 不读系统代理 | 配置 http.proxy 或开 TUN |
| SSH 连接 | Connection timed out、kex_exchange 失败 | 22 端口被封锁或限速 | ProxyCommand 或改用 443 端口 |
| 大仓库首次克隆 | 进度条走得极慢,卡在 Receiving objects | 历史提交与二进制文件体积大 | 浅克隆 / partial clone |
| raw 文件 | 脚本里的 curl 下载失败 | raw 域名不在分流规则里 | 补规则 |
| Release 附件 | 网页正常但下载只有几十 KB/s | 对象存储线路与网页不同 | 换节点 + 多线程下载器 |
| push 大改动 | 传到一半 RPC failed | 单次传输过大被中断 | 调大 postBuffer / 分批提交 |
| 容器与 CI | 本机正常,容器内失败 | 网络命名空间与环境变量隔离 | 显式传入代理配置 |
一分钟定位:到底卡在哪一步
用 GIT_CURL_VERBOSE 看 git 实际发出的请求,比盲猜有效得多。
# 让 git 输出详细的 HTTP 交互过程
GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone https://github.com/user/repo.git
如果输出停在 Connected to github.com 之后就没有下文,说明连接建立了但数据传不动;如果连 Connected 都没有,说明第一步就没通。
SSH 侧用 -T 做连通性测试:
# 测试 SSH 是否能连通(成功会返回 Hi <用户名>! 的问候语)
ssh -T git@github.com
# 看详细过程,判断卡在哪一阶段
ssh -vT git@github.com
再确认一下当前 git 到底有没有代理配置——很多人配过又忘了,或者配的端口早就变了:
git config --global --get-regexp '^(http|https)\.'
怎么给 git 单独配代理?
路径一:HTTPS 远程地址
如果你的远程地址是 https://github.com/... 开头,用这组命令:
# 端口改成你客户端实际监听的混合端口,Clash 系常见为 7890
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
# 如果客户端提供的是 SOCKS5 端口(常见为 7891)
git config --global http.proxy socks5://127.0.0.1:7891
git config --global https.proxy socks5://127.0.0.1:7891
# 取消配置
git config --global --unset http.proxy
git config --global --unset https.proxy
只给 github.com 走代理:
git config --global http.https://github.com.proxy http://127.0.0.1:7890
这条配置的含义是「只有访问 github.com 时才使用代理」,其他地址照旧直连,不会误伤内网。
路径二:SSH 远程地址
git@github.com:user/repo.git 这类地址完全不经过 http.proxy,需要在 ~/.ssh/config 里单独配置。
macOS / Linux 的写法:
# ~/.ssh/config
Host github.com
HostName github.com
User git
# 通过本地 SOCKS5 代理转发(需要系统有 nc 命令)
ProxyCommand nc -X 5 -x 127.0.0.1:7891 %h %p
ServerAliveInterval 30
Windows(Git for Windows 自带 connect.exe):
# C:\Users\<你的用户名>\.ssh\config
Host github.com
HostName github.com
User git
ProxyCommand connect -S 127.0.0.1:7891 %h %p
ServerAliveInterval 30
还有一个常被忽略的技巧:GitHub 在 443 端口上也提供 SSH 服务。很多网络对 22 端口有限制,但 443 一般畅通。
# ~/.ssh/config
Host github.com
HostName ssh.github.com
Port 443
User git
ServerAliveInterval 30
配好后用 ssh -T git@github.com 验证,看到 Hi <用户名>! You've successfully authenticated 就说明通了。
路径三:干脆开 TUN 模式
如果你不想为每个命令行工具单独配代理,直接在客户端里打开 TUN(虚拟网卡)模式。它在系统网络层接管所有程序的流量,git、ssh、npm、pip、docker 全都自动生效,不需要任何额外配置。代价是需要管理员权限,且偶尔会与部分 VPN 软件冲突。
对于长期做开发的人,TUN 模式 + 精确的分流规则通常是最省心的组合,完整的环境搭建思路见 开发者网络环境配置指南。
大仓库 clone 太慢怎么优化?
有些仓库的 .git 历史比工作目录还大,完整克隆要传几个 G。绝大多数情况下你并不需要全部历史。
浅克隆,只要最新一次提交:
# 只拉最近 1 次提交,速度提升往往在一个数量级
git clone --depth=1 https://github.com/user/repo.git
# 只要某个分支,进一步减少数据量
git clone --depth=1 --single-branch --branch main https://github.com/user/repo.git
# 后续需要完整历史时补齐
git fetch --unshallow
partial clone,保留完整历史但推迟下载文件内容:
# 不下载任何 blob,用到哪个文件才拉哪个(适合历史重要但二进制多的仓库)
git clone --filter=blob:none https://github.com/user/repo.git
# 只跳过大于 1MB 的文件
git clone --filter=blob:limit=1m https://github.com/user/repo.git
sparse-checkout,只检出你关心的子目录,适合 monorepo:
git clone --filter=blob:none --sparse https://github.com/user/repo.git
cd repo
git sparse-checkout set packages/web
克隆中断后不要从头再来。git clone 本身不支持断点续传,但可以分两步做:先建空仓库再 fetch,中断后重跑 fetch 能复用已下载的对象。
git init repo && cd repo
git remote add origin https://github.com/user/repo.git
git fetch --depth=1 origin main
git checkout FETCH_HEAD
push 超时与 RPC failed 怎么处理?
push 失败和 clone 慢的原因不一样:clone 考验下行,push 考验上行,而家用宽带的上行带宽通常只有下行的几分之一。
# 调大单次传输缓冲,缓解 RPC failed / early EOF
git config --global http.postBuffer 524288000
# 降低压缩级别,减少大文件 push 时的 CPU 等待
git config --global core.compression 0
如果一次提交里包含几百 MB 的二进制文件,再怎么调参数也难:把大文件迁到 Git LFS,或者拆成多次小提交分批推送。另外检查一下 .gitignore,误提交 node_modules、构建产物、数据集是 push 变慢的头号原因。
raw 文件和 Release 下载慢
raw.githubusercontent.com 是很多安装脚本的必经之路(各种 curl ... | bash 都依赖它),但它是独立域名,如果你的分流规则只写了 github.com,这个域名就会走直连。
检查方法:
curl -I --connect-timeout 5 https://raw.githubusercontent.com/user/repo/main/README.md
超时就说明没走代理。在客户端的规则里补上这个域名,或者临时用环境变量强制走代理:
# 临时给当前终端会话设置代理,只影响本次会话
export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890
export no_proxy=localhost,127.0.0.1,.internal.company.com
Release 附件托管在对象存储上,域名和线路都与网页不同,是最容易出现「网页秒开、下载龟速」的环节。几个实用做法:
- 用支持多线程和断点续传的下载工具,而不是浏览器默认下载。
- 下载途中不要切换节点,那会直接中断连接。
- 大附件可以先换一个地区的节点测试速度,找到快的再开始下。
curl加上-C -参数可以在中断后续传:curl -L -C - -O <附件地址>。
CI 与容器环境要注意什么
GitHub Actions 本身跑在境外机器上,通常不需要任何代理。但如果你用的是自托管 Runner,或者在国内的 CI 平台上拉取 GitHub 依赖,就需要在流水线里注入代理配置。注意:CI 里的每个 step 可能是独立 shell,export 的环境变量未必能跨 step 传递,应该在流水线级别的 env 配置里声明。
Docker 有三个互相独立的代理场景,混淆它们是最常见的错误:
- 构建镜像时(docker build 内部的网络请求)——通过 build-arg 传入:
docker build \
--build-arg http_proxy=http://host.docker.internal:7890 \
--build-arg https_proxy=http://host.docker.internal:7890 \
-t myimage .
- 容器运行时(容器内程序的网络请求)——通过环境变量传入:
docker run -e http_proxy=http://host.docker.internal:7890 \
-e https_proxy=http://host.docker.internal:7890 \
myimage
- docker pull 拉取镜像——这是 Docker 守护进程发起的请求,不受上面两者影响,需要配置守护进程本身的代理。
127.0.0.1 指向容器自己,不是宿主机。Docker Desktop 用 host.docker.internal 指向宿主机;Linux 上原生 Docker 需要用宿主机在 docker0 网桥上的地址,或者加 --add-host=host.docker.internal:host-gateway。WSL2 是另一个高频踩坑点。WSL2 有独立的虚拟网卡,Windows 上的 127.0.0.1:7890 在 WSL 内部访问不到。要么在客户端里开启「允许局域网连接」再用 Windows 主机 IP,要么开 TUN 模式让整台机器的流量统一被接管——后者更省事。
最后一点:如果你在编辑器里用 Copilot、Cursor 这类需要持续联网的 AI 工具,它们对网络的要求和 git 不完全一样(长连接、对延迟敏感、部分走 WebSocket),单独配 git 代理并不能让它们正常工作,具体配置见 Cursor 与 Copilot 网络配置指南。