网络诊断 开发者网络 基础

GitHub 访问慢、git clone 卡住、push 超时的完整解决方案

最常见的原因是开了系统代理但 git 没走:git 和 SSH 有自己的一套代理配置,必须单独设置才生效。

发布: 更新: 审阅: 约 6 分钟阅读

先说最常见的一种情况:浏览器打开 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
注意上面的写法是全局生效的,会连带影响公司内网 GitLab、私有 Gitea 等所有 https 仓库。更稳妥的是只对 GitHub 配置。

只给 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 有三个互相独立的代理场景,混淆它们是最常见的错误:

  1. 构建镜像时(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 .
  1. 容器运行时(容器内程序的网络请求)——通过环境变量传入:
docker run -e http_proxy=http://host.docker.internal:7890 \
           -e https_proxy=http://host.docker.internal:7890 \
           myimage
  1. 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 网络配置指南。

常见问题

为什么浏览器能正常打开 GitHub,git clone 却一直卡在 0%?
因为浏览器和 git 走的是两套代理配置。开启客户端的「系统代理」只会写入操作系统的代理设置,浏览器会读取它,而 git 和 ssh 命令默认不读,仍然直连。解决办法是给 git 单独配置 http.proxy,或者给 SSH 配置 ProxyCommand,也可以开启客户端的 TUN 模式让所有程序的流量都被接管。判断方法很简单:网页正常而命令行卡住,就是这个原因。
配了 http.proxy 之后为什么 git@github.com 的仓库还是连不上?
http.proxy 只对 https:// 开头的远程地址生效,SSH 协议完全不经过它。git@github.com:user/repo.git 这种地址走的是 22 端口的 SSH 连接,需要在 ~/.ssh/config 里用 ProxyCommand 配置代理,或者把远程地址改成 https 形式。另一个常见做法是改用 GitHub 的 443 端口 SSH 服务(ssh.github.com:443),在很多网络里比 22 端口更稳定。
git clone 到一半报 RPC failed 或 early EOF 怎么办?
这通常是单次传输的数据量太大,连接在中途被中断。先把 http.postBuffer 调大到 500MB 左右缓解;如果仓库本身很大,更有效的办法是改用浅克隆 --depth=1 先拿到最新代码,需要历史时再用 fetch --unshallow 补齐。对于超大仓库,还可以用 partial clone 把 blob 推迟到实际需要时再下载。
GitHub Release 的附件下载特别慢,有什么办法?
Release 附件托管在对象存储上,域名与网页不同,走的线路也不一样,所以经常出现网页秒开、附件几十 KB/s 的情况。先确认你的代理规则里包含了这个下载域名而不只是 github.com;如果仍然慢,改用支持多线程与断点续传的下载工具,或者换一个地区的节点重试。不要在下载到一半时切换节点,那会直接中断传输。
在 Docker 容器里 git clone 失败,但宿主机可以,为什么?
容器有独立的网络命名空间,127.0.0.1 指向容器自己而不是宿主机上的代理端口。需要把代理地址改成宿主机在容器网络中的地址(Docker Desktop 上是 host.docker.internal),或者用 --network host 让容器共享宿主机网络。另外构建镜像时环境变量不会自动带入,要通过 build-arg 显式传入 http_proxy 与 https_proxy。
给 git 配了全局代理,拉公司内网仓库会受影响吗?
会。--global 的 http.proxy 对所有 https 远程地址生效,包括内网 GitLab,结果是内网请求被送到代理再绕回来,轻则变慢重则失败。正确做法是用 http..proxy 只对 github.com 配置代理,或者设置 no_proxy 环境变量排除内网域名,也可以在具体仓库目录里用不带 --global 的配置单独设置。

↑ 返回顶部