什么';两个git commit有相同的'abbrev commit'的可能性`

什么';两个git commit有相同的'abbrev commit'的可能性`,git,Git,两个git提交有相同的abbrev提交 我看到git history默认显示git abbrev commit以简化和美观。 但是在一次git回购中出现两个相同的abbrev提交的可能性有多大。 或者更确切地说:在回购协议中发生SHA1冲突的可能性相同 当git命令返回缩略引用列表时,如果发现两个缩略语(哈希摘要的前缀)相同,它会将完整SHA1哈希中的更多字符添加到这些特定引用中,直到它们不再相同。有几种不同的方法来回答这个问题。你可以用数学告诉你在各种条件下的机会。另一个问题是问Git实际上做

两个git提交有相同的
abbrev提交

我看到git history默认显示git abbrev commit以简化和美观。 但是在一次git回购中出现两个相同的
abbrev提交的可能性有多大。
或者更确切地说:在回购协议中发生SHA1冲突的可能性相同


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

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

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

因为StackOverflow没有格式化LaTeX,所以我在这里有一个截图,来自我自己(正在编写)的书的第77页。我做的有点太大了抱歉:

要找到所需的数字,请将n和r替换为正确的值并计算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
这个存储库大约有300000个对象(大多数是打包的;只有49个松散的对象),所以n大约是300k。您的存储库当然会有所不同

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

Git实际上做什么 如果使用
git-rev-parse--short=number
git-log--abbrev=number--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
}
长度=
环路{
使用字符生成短哈希
short hash是否明确无误?如果是,则完成-退出循环
增量长度
}
这样就不可能与现在的对象发生碰撞

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

当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;
+               }
+       }
+if(len<16&&!status&&(flags&GET\u SHA1\u AUTOMATIC)){
+无符号整数预期碰撞=1预期碰撞){
+默认值\u automatic\u abbrev=len+1;
+返回短\u名称\u不明确;
+               }
+       }
对于Git2.11,这是一个很好的例子。随后在年对其进行了改进。但50%的概率太高了。

正如我在“”中提到的,只需拨打

通过输入一个太短的长度,您将强制Git返回实际的最小长度,这保证了存储库的SHA1唯一性


获取git rev parse--short=4的返回sha1的最小长度,您就不会有任何问题。

Slim。它是一个随机散列,所以它非常小。可能是由于没有压缩提交而意外导致的。我得等我自己去弄清楚我是怎么做到的。我只是在猜测