使用--reference引用无Blob克隆时Git Clone报错的原因
我尝试通过引用一个用--filter=blob:none创建的现有裸克隆来加速完整克隆操作(注:我确实想要创建新仓库,而非执行fetch --unshallow这类操作)。原本期望缺失的对象会像通常一样从对应远程获取,但实际执行时出现报错:
% git clone --filter=blob:none --quiet --bare git@github.com:HaleTom/dotfiles.git blobless % git clone --reference blobless git@github.com:HaleTom/dotfiles.git new-clone Cloning into 'new-clone'... error: cannot read object e8b079d8b0914612a87fb89ecd2d3c67eebe3628 '.gitignore' <snip> error: cannot read object e5bf7b3310b268d7bbd15edec5d1aecd7b87e2d5 'zsh/.config/zsh/zle' fatal: unable to checkout working tree warning: Clone succeeded, but checkout failed. You can inspect what was checked out with 'git status' and retry with 'git restore --source=HEAD :/'
Git Clone手册中关于--filter=blob:none的说明:
过滤所有Blob(文件内容),直到Git需要时再获取
为何实际执行时报错,而非按手册所述在需要时获取Blob?
原因
当你用--reference指向一个通过--filter=blob:none创建的裸克隆时,Git会优先从这个本地引用仓库查找对象,但该仓库本身没有存储任何blob文件。而新克隆的仓库并未启用partial clone模式(你没有给它加--filter参数),所以Git在checkout过程中不会自动触发从远程拉取缺失的blob——按需拉取逻辑只有在仓库自身配置了过滤规则时才会生效。
解决办法
有两种可行方案:
让新克隆仓库启用partial clone,自动按需拉取
克隆时同时添加--filter=blob:none参数,这样新仓库本身会启用partial clone模式,checkout时会自动从远程拉取缺失的blob,同时利用引用仓库的现有对象加速:git clone --filter=blob:none --reference blobless git@github.com:HaleTom/dotfiles.git new-clone这种方式下,工作树会完整生成,仓库后台会按需拉取所需blob,符合你想要的加速效果。
先完成克隆,手动触发拉取缺失blob
按你原本的命令完成克隆后,执行报错提示的命令即可触发Git从远程拉取缺失的blob,生成完整工作树:git restore --source=HEAD :/这个命令会尝试恢复所有文件,此时Git发现本地引用仓库没有对应blob,就会自动从远程获取。
内容的提问来源于stack exchange,提问作者Tom Hale

