这在现实世界中可能从未发生过,也可能永远不会发生,但让我们考虑一下:假设您有一个 git 存储库,进行提交,然后变得非常非常不幸:其中一个 blob 最终具有相同的 SHA-1作为另一个已经在您的存储库中的。问题是,Git 将如何处理这个问题?只是失败?找到一种方法来链接这两个 blob 并根据上下文检查需要哪一个?
与其说是一个实际的问题,不如说是一个脑筋急转弯,但我发现这个问题很有趣。
我做了一个实验来确切了解 Git 在这种情况下的行为方式。这是版本 2.7.9~rc0+next.20151210(Debian 版本)。我基本上只是通过应用以下差异并重建 git 将哈希大小从 160 位减少到 4 位:
--- git-2.7.0~rc0+next.20151210.orig/block-sha1/sha1.c +++ git-2.7.0~rc0+next.20151210/block-sha1/sha1.c @@ -246,6 +246,8 @@ void blk_SHA1_Final(unsigned char hashou blk_SHA1_Update(ctx, padlen, 8); /* Output hash */ - for (i = 0; i < 5; i++) - put_be32(hashout + i * 4, ctx->H[i]); + for (i = 0; i < 1; i++) + put_be32(hashout + i * 4, (ctx->H[i] & 0xf000000)); + for (i = 1; i < 5; i++) + put_be32(hashout + i * 4, 0); }
然后我做了一些提交并注意到以下内容。
对于#2,当你运行“git push”时,你通常会得到这样的错误:
error: object 0400000000000000000000000000000000000000 is a tree, not a blob fatal: bad blob object error: failed to push some refs to origin
要么:
error: unable to read sha1 file of file.txt (0400000000000000000000000000000000000000)
如果您删除该文件,然后运行“git checkout file.txt”。
对于 #4 和 #6,您通常会收到如下错误:
error: Trying to write non-commit object f000000000000000000000000000000000000000 to branch refs/heads/master fatal: cannot update HEAD ref
运行“git commit”时。在这种情况下,您通常可以再次键入“git commit”,因为这将创建一个新的哈希(因为更改了时间戳)
对于 #5 和 #9,您通常会收到如下错误:
fatal: 1000000000000000000000000000000000000000 is not a valid 'tree' object
运行“git commit”时
如果有人试图克隆您损坏的存储库,他们通常会看到如下内容:
git clone (one repo with collided blob, d000000000000000000000000000000000000000 is commit, f000000000000000000000000000000000000000 is tree) Cloning into 'clonedversion'... done. error: unable to read sha1 file of s (d000000000000000000000000000000000000000) error: unable to read sha1 file of tullebukk (f000000000000000000000000000000000000000) fatal: unable to checkout working tree warning: Clone succeeded, but checkout failed. You can inspect what was checked out with 'git status' and retry the checkout with 'git checkout -f HEAD'
我“担心”的是,在两种情况下(2,3),存储库在没有任何警告的情况下损坏,在 3 种情况下(1,7,8),一切似乎都正常,但存储库内容与您的预期不同成为。克隆或拉取的人将拥有与您拥有的内容不同的内容。案例 4、5、6 和 9 都可以,因为它会因错误而停止。我想如果至少在所有情况下都失败并出现错误会更好。