每个团队里都有这么一位同事。同样的仓库、同样的网络、同样的 Mac,他 git pull 是几秒钟的事,你这边转半天还在 "Receiving objects: 12%"。同样 git clone 一个 5 GB 的仓库,他喝杯咖啡回来已经 ready,你这边眼看快下班了还没拉完。
这事其实没那么玄学。git pull 慢,可以从客户端、协议、网络三个层面拆开看——更多时候是网络层在拖后腿,而你恰好在网络条件更差的那一侧。
一、先排除最容易自查的客户端层
在怀疑网络之前,先看几个能自己解决的事。
仓库本地状态。 仓库太大、对象太多时,每次 pull 都会触发 git 的对象解析。如果你长期不做 gc,本地 .git 目录里散落着大量 loose objects,pull 时合并写入也会变慢。先跑一遍 git gc --aggressive 看看是否改善。
fetch 范围。 默认 git pull 会从远端拉取所有引用。如果你的仓库分支很多(几百上千个),可以在配置里限定只拉当前分支的远端引用(fetch.refspec),减少协商往返。
克隆策略。 如果你只是想跑一下代码、不需要历史,可以用浅克隆(--depth=1),把几个 GB 的历史压缩到几十 MB。日常协作场景不适合,但临时拉代码或 CI 场景非常实用。
这些都是相对小的优化。如果排查完发现你和同事的本地配置基本一致,问题大概率不在你这边。
二、协议层:HTTPS 还是 SSH
Git 支持多种传输协议,HTTPS 和 SSH 是最常见的两种。两者底层都是 TCP,但行为细节不同。
HTTPS 走 443 端口,每次请求都会经过 TLS 握手;好处是穿透防火墙友好,几乎所有网络环境都能用。SSH 走 22 端口,复用长连接,少了反复握手的成本,对频繁 pull 的场景更友好。
但这两者的速度差异,在常规公网链路上其实不大——单次连接的 TLS 握手开销可能就几十毫秒。真正放大它们差距的,是底层链路本身的延迟和丢包。一旦链路 RTT 上到几百毫秒、有丢包,HTTPS 的握手代价会被放大;而 SSH 的长连接在 TCP 重传机制下也会拖慢吞吐。换句话说,协议层的差异,会被网络层的差异放大。
三、真正的元凶:跨境网络
如果你的团队代码托管在 GitHub、GitLab.com、Bitbucket,或者你们公司的 GitLab/Gitea 部署在海外,那么 git pull 慢的根本原因往往就一个——跨境公网链路。
这里有几个具体机制:
RTT(往返时延)放大。 国内到 GitHub 在美西的机房,公网 RTT 通常在 200~300ms,糟糕的时候会到 400ms 以上。git 协议在拉取大仓库时会有多次小请求往返(协商引用、拉对象索引、流式传输),每一次往返都要乘上这个 RTT,叠加起来体感就是"转半天没动"。
TCP 拥塞窗口起不来。 跨境链路的丢包率本来就比国内高,丢包会触发 TCP 的拥塞控制——窗口减半、慢启动。一个 5 GB 的仓库,理论上你的带宽足够几分钟下完,但拥塞窗口反复被打回起点,实际吞吐可能只能跑到峰值的 1/5。
链路绕路。 公网的 BGP 路由不一定走最优路径。从北京到旧金山,运气好的时候走太平洋海缆直达,运气不好的时候可能绕一圈日本、新加坡、再到美西,多出来的几跳每一跳都在加延迟和丢包概率。
坐你旁边的同事为什么快? 几个可能:他用了网络加速、他离运营商出口更近、他工位的 Wi-Fi AP 跟你不一样、或者他赶在了链路相对空闲的时段。最常见的还是第一种。
四、那些 git 自身能做的优化(有上限)
git 社区也意识到了这个问题,做了不少协议层优化:
Protocol v2。 较新版本的 git 默认启用,减少了引用协商阶段的数据量。对分支特别多的大型 monorepo 提升明显,但解决不了底层延迟问题。
Partial Clone / Sparse Checkout。 只克隆部分对象或部分目录,对超大仓库有用。代价是首次访问历史时会按需拉取,体验上的延迟换到了别处。
镜像加速服务。 GitHub 在国内有过若干镜像方案,但稳定性参差。一些云厂商提供的 git 镜像加速对常用开源项目有效,对你自己的私有仓库帮不上忙。
这些方案的共同上限是:它们都是在公网链路质量"给定"的前提下做的优化。当公网链路本身就在丢包绕路,这些优化的天花板就被钉死了。
五、把跨境链路本身做稳
回到根本问题:如果 git 慢是因为跨境公网链路差,那解法就是不走或少走公网。
业界比较成熟的方向是用专业的网络加速或 SD-WAN 服务接管跨境流量。基本思路是这样的:你的 git 流量先就近接入服务商在国内的接入节点(POP),再走服务商优化过的骨干线路出海到目标机房附近,最后落地到 GitHub 或你自己的海外代码服务器。
为什么这种方式能快?三点:
一是路径优化。不再受公网 BGP 绕路的影响,骨干线路是预选过、质量监控过的,RTT 通常能比公网降低 30% 到 60%。
二是丢包改善。骨干链路的丢包率远低于公网国际段,TCP 拥塞窗口能稳定打开,跑满带宽不再是奢望。
三是协议优化。一些方案会在加速节点上做 TCP 参数调优、协议复用、压缩传输等处理,对 git 这种"多次往返 + 大对象流式"的协议特别友好。
实际效果上,业界已有团队反馈:克隆同一个 5 GB 量级的仓库,公网链路要 40 分钟,走加速链路压到 4 分钟左右,差不多十倍提升。这个量级的差距,对每天要 pull 几次代码的研发团队,是直接体感的效率变化。
写在最后
git pull 慢这件事,单看一次没什么,看一年就是数百小时的等待。对小团队是隐性内耗,对中大型研发团队是真金白银的成本。
如果你团队的代码托管在海外,又经常听到"今天网络又抽风了"这种抱怨,问题大概率不在 git、不在 IDE、不在你的同事。把跨境这条链路本身做稳,往往比换工具、调参数、换协议来得直接得多。
下次再被同事的 pull 速度刺激到的时候,不妨先问一句:他是不是走的不一样的路?