git fetch 实现断点续传
Posted | stdout
git fetch origin main --depth=1 一次只下一个 pack,包含所有缺失对象,国内这网络你懂的,断开就废了,然后从头下载,往往又出事;
老外不懂国内网络条件这么艰苦,只能自己让AI改造。结果:
https://github.com/est/snippets/tree/master/git-fr
步骤:
git fetch --filter=blob:none --depth=1—— 只拉 commit+tree,这个速度很快,只有KB级别的传输- 用
rev-list --objects --missing=print算缺失集合,500 个 blob 一批回填 - 每轮重算缺失、只补缺的。
踩过的坑
git fetch origin <blobsha>每次都会打印fatal: bad object <sha>+error: ... did not send all necessary objects,但事后检查对象blob却真的下载了。后来发现因为cat-file会拉数据,rev-list --missing=print不会。- 普通
git fetch origin <sha>拿到的 pack 是薄包(thin pack)——服务器按客户端声明做 delta 压缩。如果本地声明的是refs/remotes/origin/main(一个 commit),服务器据此假定我们拥有整棵树的全部 blob所以就啥都不给 - 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