Git 损坏"unable to read [sha]"但 git fsck 报告没有错误



我有一个 git 存储库,里面似乎缺少一个 blob。git gcgit repack失败,抱怨"致命:无法读取 89a9259486af9e3f0b24f3338ec39b18a7ba39c3"。但是,git fsck找不到问题。我知道我可能不得不在某个地方删除和修剪一个分支,但我无法弄清楚在哪里。有人可以指出我如何调试和解决"无法阅读"问题吗?

git 版本是 2.16.4,但版本 2.8.3 中可能发生损坏。

该 blob 不是存在于"官方"存储库中的 blob,因此它可能只属于本地分支/reflog/等。有许多当地分支机构和

此存储库上有许多工作树,并且在其生存期内可能已添加、删除和修剪了工作树。

调试信息:

git repack -adfb --max-pack-size=256m --window=40 --window-memory=100m Counting objects: 5999778, done. Delta compression using up to 4 threads. Compressing objects: 100% (5983452/5983452), done. warning: disabling bitmap writing, packs are split due to pack.packSizeLimit fatal: unable to read 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

我尝试了几个不同的 fsck 命令行,结果都相同:

$ > git fsck --cache --no-dangling --name-objects --progress
Checking object directories: 100% (256/256), done.
Checking objects: 100% (14155357/14155357), done.
Checking connectivity: 6003771, done.

.

git show 89a9259486af9e3f0b24f3338ec39b18a7ba39c3
fatal: bad object 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

.

$ > git branch --contains 89a9259486af9e3f0b24f3338ec39b18a7ba39c3 --all
error: no such commit 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

这是我之前出于其他目的从互联网上获取的脚本,但我认为它可能会有所帮助:

$ > /tmp/git_blob_to_commit.pl 89a9259486af9e3f0b24f3338ec39b18a7ba39c3
[no ouptput]

请注意,这是一个巨大的回购,因此 gc/repack 操作需要很长时间,所以如果您给我一些建议,我不会忽略它,我可能会尝试它,但需要几个小时才能回复您它是如何进行的。

更新重新运行命令按 [return] 几次,您可以看到错误不在压缩阶段。也许正处于写作阶段。(?)

Counting objects: 6006957, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5990610/5990610), done.
Writing objects:  19% (1193602/6006957)
warning: disabling bitmap writing, packs are split due to pack.packSizeLimit
Writing objects:  26% (1579434/6006957)
Writing objects:  63% (3802470/6006957)
fatal: unable to read 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

这是一个棘手的情况,旧版本的 git 会错误地修剪工作树上的索引实际使用的对象。

这是我采取的粗略方法。它肯定可以优化,但我希望永远不必再这样做了。

for i in $(git worktree list | awk '{print $1}')
do
cd $i
echo "TITLE $i"
git ls-files --stage
done  >> /tmp/blobs.txt         # This is potentially a massive file
for i in $(cat /tmp/blobs.txt | awk '{print $2}')  # Brute force, could be optimized
do
git show $i >/dev/null || echo "NOT FOUND $i"
done

对于每个"未找到"条目,运行egrep "TITLE|<sha>" /tmp/blobs.txt以查找它所在的工作树。 然后转到工作树并取消索引中的任何内容。这应该可以解决问题。


感谢@torek提供信息来得出这个结论。(你有足够的声誉,我认为你不会介意没有得到这个答案的分数。

git repack -adfb --max-pack-size=256m --window=40 --window-memory=100m
...
Compressing objects: 100% (5983452/5983452), done.
...
fatal: unable to read 89a9259486af9e3f0b24f3338ec39b18a7ba39c3

看起来该对象未从任何地方引用,否则您将无法通过"压缩"阶段,并且在清理对象期间发生故障。您可以通过运行带有--dangling--unreachable的 fsck 来验证它 - 它会将其打印在列表中,甚至失败。

最新更新