我在我的
书中提供了一个公式——见第78-79页,但如果您正在寻找一个简单的公式,当您大约散列2
n/2个密钥时,某些哈希冲突的概率达到约50%。SHA-1哈希本身是160位,表示为40个十六进制数字,每个数字表示160位中的4位。将其截断为7个十六进制数字会留下28位,因此您将在大约2
14个密钥或16384个对象处达到50%碰撞几率。如果您将对象限制为仅提交,则这是相当可观的提交数,但Git将所有对象(提交、树、注释标记对象和blob)放入单个哈希索引的键值存储中。
< p >任何给定键对的哈希碰撞概率只有2
n 中的1,即2
28 或268百万分之一。随着键的数量增加,它迅速增加到50%的原因被称为生日悖论或
birthday problem。当然,50%太可怕了;使用28位,如果我们希望总体概率低于0.1%,则应将对象数量保持在约1230以下。通过转向32位(8个字符缩写),我们将其加倍到约2460,但这仍然不是很多对象。
当您的存储中有16k个对象时,您可能应该至少使用10个十六进制数字,提供2 40 个可能的哈希值和大约.99987794的p-bar值...(约占碰撞机会的.019%)。九个十六进制数字仅提供2 36 个哈希值,产生.99804890的p-bar或0.19%的碰撞几率,我认为这太高了。
如果你能将含糊匹配代码限制在提交或者提交点上,或者只使用 Git 中的提交或已注释标签(commit-ish),内置默认值就能很好地工作。(Git 在许多情况下实际上会这样做。)但是,至少在我看来,Git 用于计算“正确”缩写长度的内部代码过于随意,太松散了,因为它在可能用于标识任何对象的上下文中使用了 50% 碰撞概率平方根技巧。
(正如评论中所指出的,Git 内部始终使用完整哈希值。只有在非 Git / Git 接口,例如
git log <hash>
或
git show <hash>
用户界面命令时,才可以键入缩写哈希值或请求缩写输出哈希值。在这里,Git 将默认使用 50% 碰撞概率数来计算要显示多少个字符,从数据库中对象数量的估计开始。如果您正在提供哈希值,则由您决定提供多少。如果您要求 Git 提供它,则仍然可以选择使用
--abbrev=number
来决定显示多少位。请注意,最小值为 4:
git log abc
不会将
abc
视为哈希 ID,但是
git log abcd
将把
abcd
视为哈希 ID 的缩写。默认使用非常旧的 7 个字符,来自 Git 1.7 左右的版本。)
16^长度
。任何措施可能都需要从源代码中挖掘出来。 - jhpratt