【问题标题】:what's the chance that two git commit have same `abbrev-commit`两个 git commit 有相同的 `abbrev-commit` 的机会是什么
【发布时间】:2019-12-12 13:18:06
【问题描述】:

两个 git commit 有相同 abbrev-commit 的机会是什么

我看到 git history default show git abbrev-commit 是为了简化和美观。 但是两个相同的abbrev-commit 出现在一个 git repo 中的机会有多大?

【问题讨论】:

  • 苗条。非常苗条
  • 如何计算准确
  • 它是一个随机散列,所以它非常小。也许你是因为没有压缩你的提交而意外造成的。我将不得不等待自己找出如何后方。我只是在这里猜测

标签: git


【解决方案1】:

有几种不同的方法可以回答这个问题。一个人使用数学来告诉你在各种提议的条件下会是什么的机会。另一个是问 Git 实际上做了什么,但是当问 那个 问题时,答案取决于你的特定 Git 版本。

数学答案

机会取决于缩写的长度存储库中对象的数量。 (在某些情况下,如果您知道所需的对象类型,如果潜在匹配描述 不同 对象类型,则可以消除冲突的歧义。在这种情况下,您可以简单地减少值 n在下面的公式中。)

由于 StackOverflow 不格式化 LaTeX,我在这里有一张来自我自己(进行中)书的第 77 页的屏幕截图。我把它弄得太大了——抱歉:

要找到你想要的数字,用正确的值替换 nr 并计算 p-bar,然后从 1 中减去它。N 是对象:

$ git count-objects -v
count: 49
size: 568
in-pack: 307916
packs: 40
size-pack: 176024
prune-packable: 0
garbage: 0
size-garbage: 0

这个存储库有大约 300,000 个对象(大部分是打包的;只有 49 个松散的对象),所以 n 大约是 300k。您的存储库当然会有所不同。

然后,为 r 插入正确的值。如果您使用 完整 散列,则 r 的值为 2160,或 1461501637330902918203684832716283019655932542976。如果您将散列缩写为四个字符 - 这是Git 将接受的最小输入为 216 或 65536,因为每个字符提供 4 位。完整哈希的长度为 40 个字符,因此完整哈希公式中的长度为 160。

Git 实际做了什么

如果您使用git rev-parse --short=<em>number</em>git log --abbrev=<em>number</em> --abbrev-commit,则由您自己选择长度。如果您没有提供数字,Git 会使用不合适的公式选择一个数字。1 但它不仅仅使用该数字!

现代 Git 检查缩写哈希在当前数据库中是否唯一。这不是一个概率猜测,它只是一个字面测试,循环执行:

length = <whatever>
loop {
    generate short hash using <length> characters
    is short hash unambiguous? if so, we're done - exit the loop
    increment length
}

这样就不会与您现在拥有的对象发生碰撞

不幸的是,如果您再添加一个对象,新对象可能会与基于旧对象生成的缩写哈希冲突。使用上面的公式计算这个概率,知道所有现有的键都没有碰撞,加上缩写哈希长度隐含的 r 的值。它可能仍然相当不错,因为即使是 4 个字符也可以让您获得 1-out-of-65536。但请注意,随着您添加更多对象,它会迅速恶化。

当 Linus Torvald 的第一段代码进入 Git 2.11 时,这个循环检查代码就已经存在。我不确定一个人必须回到它没有发生的地方多远,但在一些非常旧的 Git 版本中肯定没有发生。


1从 Git 2.11 开始,Git 使用的事实是,对于大量 n 个键,50% 的冲突率发生在n = sqrt(r)。 Linus Torvalds 添加了这段代码:

+       if (len < 16 && !status && (flags & GET_SHA1_AUTOMATIC)) {
+               unsigned int expect_collision = 1 << (len * 2);
+               if (ds.nrobjects > expect_collision) {
+                       default_automatic_abbrev = len+1;
+                       return SHORT_NAME_AMBIGUOUS;
+               }
+       }

commit e6c587c733 中用于 Git 2.11。随后在commit 8e3f52d778 中对其进行了改进。但是 50% 的概率太高了。

【讨论】:

    【解决方案2】:

    零。 或者更确切地说:您的存储库中存在 SHA1 冲突的可能性相同。

    当一个 git 命令返回一个缩写 refs 的列表时,如果它发现两个缩写词(哈希摘要的前缀)是相同的,它会从完整的 SHA1 哈希中添加更多字符到这些特定的 refs,直到它们不再相同。

    【讨论】:

      【解决方案3】:

      正如我在“How much of a git sha is generally considered necessary to uniquely identify a change in a given codebase?”中提到的,只需调用git rev-parse --short=4

      通过设置一个短的长度,你将强制 Git 返回保证该存储库的 SHA1 唯一性的实际最小长度。

      得到git rev-parse --short=4返回的sha1的最小长度就没有问题了。

      【讨论】:

        猜你喜欢
        • 2011-07-07
        • 2018-03-27
        • 1970-01-01
        • 2022-10-20
        • 2011-02-14
        • 2015-09-28
        • 1970-01-01
        相关资源
        最近更新 更多