git - Git 将如何处理 blob 上的 SHA-1 冲突?

标签 git hash-collision

这在现实世界中可能从未发生过,也可能永远不会发生,但让我们考虑一下:假设您有一个 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);
 }

然后我做了一些提交并注意到以下内容。

  1. 如果具有相同散列的 blob 已经存在,您根本不会收到任何警告。一切似乎都很好,但是当你推送时,有人克隆,或者你恢复,你将失去最新版本(符合上面的解释)。
  2. 如果树对象已经存在并且您使用相同的散列创建一个 blob:一切看起来都很正常,直到您尝试推送或有人克隆您的存储库。然后您会看到 repo 已损坏。
  3. 如果一个提交对象已经存在并且你创建了一个具有相同散列的 blob:与#2 相同 - 损坏
  4. 如果 blob 已经存在并且您使用相同的哈希创建提交对象,则更新“ref”时会失败。
  5. 如果一个 blob 已经存在并且你创建了一个具有相同散列的树对象。创建提交时会失败。
  6. 如果树对象已经存在并且您使用相同的哈希创建提交对象,则更新“ref”时会失败。
  7. 如果一个树对象已经存在并且你用相同的散列创建一个树对象,一切看起来都很好。但是当您提交时,所有存储库都将引用错误的树。
  8. 如果一个提交对象已经存在并且你用相同的散列创建一个提交对象,一切看起来都很好。但是当你提交时,永远不会创建提交,并且 HEAD 指针将移动到旧提交。
  9. 如果提交对象已经存在并且您使用相同的哈希创建树对象,则创建提交时会失败。

对于 #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),一切似乎都正常,但存储库内容与实际情况不同你期望它是。克隆或 pull 的人将具有与您所拥有的不同的内容。情况 4、5、6 和 9 没问题,因为它会因错误而停止。我想如果它至少在所有情况下都失败并出现错误会更好。

关于git - Git 将如何处理 blob 上的 SHA-1 冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9392365/

相关文章:

python - python集中的哈希表冲突?

hash - 为 UTF16 中的文件路径寻找一个好的 64 位哈希

swift - Dictionary 在 Swift 中如何使用 Equatable 协议(protocol)?

git - CentOS:如何根据以下内容在 CentOS 服务器上设置 GIT

ruby - Git 提交消息的正则表达式

Git 和团队基础服务器

java - Jdeveloper 11.1.1.4.0 11c 的 Git 扩展

git - 仅可视化 git 分支拓扑,没有提交历史

c# - .NET 字典如何解决冲突?

java - 存储在同一个存储桶中的元素在重新哈希后是否可以重新分配到单独的存储桶中?