git fetch 实现断点续传

git fetch origin main --depth=1 一次只下一个 pack,包含所有缺失对象,国内这网络你懂的,断开就废了,然后从头下载,往往又出事;

老外不懂国内网络条件这么艰苦,只能自己让AI改造。结果:

https://github.com/est/snippets/tree/master/git-fr

步骤:

  1. git fetch --filter=blob:none --depth=1 —— 只拉 commit+tree,这个速度很快,只有KB级别的传输
  2. rev-list --objects --missing=print 算缺失集合,500 个 blob 一批回填
  3. 每轮重算缺失、只补缺的。

踩过的坑

  1. git fetch origin <blobsha> 每次都会打印 fatal: bad object <sha> + error: ... did not send all necessary objects,但事后检查对象blob却真的下载了。后来发现因为cat-file 会拉数据,rev-list --missing=print 不会。
  2. 普通 git fetch origin <sha> 拿到的 pack 是薄包(thin pack)——服务器按客户端声明做 delta 压缩。如果本地声明的是 refs/remotes/origin/main(一个 commit),服务器据此假定我们拥有整棵树的全部 blob所以就啥都不给
  3. git 原生 lazy fetch ,用 GIT_TRACE=1 git cat-file blob <missing> 抓到了 git 自己 lazy fetch 时实际执行的命令:
git -c fetch.negotiationAlgorithm=noop fetch origin --no-tags \
  --no-write-fetch-head --recurse-submodules=no --filter=blob:none --stdin

关键:
- fetch.negotiationAlgorithm=noop —— 不发 haves,服务器没法薄包化,只能发完整对象;
- --filter=blob:none —— 显式声明的 want 会绕过过滤器直接发送(partial clone 语义);
- --stdin —— want 列表从 stdin 读,天然支持批量。

还有很多放到 README.md 里了

安装

fr.sh 放到 PATH(如 ~/.local/bin/git-fr),即可 git fr 使用。

git config --global alias.fr '!<绝对路径>/fr.sh'

感觉,现在搞这些东西似乎意义不大了?反正大家都是让AI自己临时写一个脚本。。。🤣

有空让AI写个支持多线程并发 fetch 的。

Comments