Git散列副本

Git散列副本,git,hash,probability,Git,Hash,Probability,Git允许使用以下命令检索提交的哈希值: git rev-parse HEAD 它给出了33b316c 或 其中给出了33b316cbeeab3d69e79b9fb659414af4e7829a32 我知道长哈希在实践中永远不会发生冲突 在实践中,短散列的使用频率更高。我想知道短的碰撞的概率是多少?git是否采取了任何措施来克服可能的冲突(例如使用git checkout)?回购协议的短哈希列表中出现重复项的可能性随着提交次数的增加而快速增加 但是,它不会引起太多问题,因为这些根本不是唯一的,

Git允许使用以下命令检索提交的哈希值:

git rev-parse HEAD
它给出了
33b316c

其中给出了
33b316cbeeab3d69e79b9fb659414af4e7829a32
我知道长哈希在实践中永远不会发生冲突


在实践中,短散列的使用频率更高。我想知道短的碰撞的概率是多少?git是否采取了任何措施来克服可能的冲突(例如使用
git checkout
)?

回购协议的短哈希列表中出现重复项的可能性随着提交次数的增加而快速增加

但是,它不会引起太多问题,因为这些根本不是唯一的,它们只是一个舒适的特性,提供了在某些命令中指定提交的替代方法

当您选择向命令提供一个简短的散列,并且它在您的repo中实际上是不明确的(即,无法解析为唯一的提交),git会提示您一个候选列表,您可以选择要调用的

示例输出:

$ git checkout 2334
error: short SHA1 2334 is ambiguous
hint: The candidates are:
hint:   233475fec8 commit 2018-02-14 - Merge pull request #175 in someRepo from someBranch to someOtherBranch
hint:   2334790f05 commit 2018-06-14 - Merge pull request #917 in someRepo from someBranch to yetAnotherBranch
hint:   233415cfa2 tree
hint:   233438d772 tree
hint:   23348a014a tree
error: pathspec '2334' did not match any file(s) known to git
例如,这是用于在CLI中键入的
git checkout
,但我不确定它在脚本上下文中的行为。要么是退出代码1出错,要么是自动选择一个候选项,我必须对此进行检查。

我在我的文章中给出了一个公式——见第78-79页——但如果你想找一个简单的公式,在n位哈希中,某个哈希冲突概率达到50%的点是当你哈希大约2n/2个键时。SHA-1散列本身是160位,表示为40个十六进制数字,每个数字表示160位中的4位。将其截断为7个十六进制数字将保留28位,因此在大约214个键或16384个对象时发生冲突的几率将达到50%。如果将对象约束为仅提交,那么提交的数量相当可观,但Git将所有对象提交、树、带注释的标记对象和blob放在一个散列索引键值存储中

任何给定密钥对的哈希冲突概率仅为2n分之一,即228分之一或2.68亿分之一。随着钥匙数量的增加,它会快速增加到50%,这被称为生日悖论或是死亡悖论。50%当然太可怕了;对于28位,如果我们希望总体概率低于0.1%,我们应该将对象数保持在大约1230以下。通过使用32位(8个字符的缩写),我们将其翻倍到大约2460个,但这仍然不是很多对象

当您的存储中有16k个对象时,您可能应该使用至少10个十六进制数字,给出240个可能的散列值和大约.99987794的p-bar值。。。(大约0.019%的碰撞概率)。九个十六进制数字只给出236个散列值,产生一个.99804890的p-bar。。。或者0.19%的碰撞概率,我认为这太高了

如果您可以将不明确的匹配代码限制为仅提交或仅提交ish,这在Git中意味着提交或带注释的标记,那么内置的默认值工作得非常好。(事实上,Git在很多情况下都会这样做。)但Git计算“正确”缩写长度的内部代码,至少在我看来,也太不小心了,因为它在产生的哈希可能用于识别任何对象的上下文中使用了50%碰撞概率平方根技巧


(如评论中所述,Git内部总是使用完整的哈希值。只有在非Git/Git界面,例如,
Git log
Git show
面向用户的命令中,您才可以键入缩写的哈希值,或请求缩写的输出哈希值。在这里,Git将默认使用50%的冲突概率数来计算哈希值。)要显示的字符很多,首先是数据库中对象数量的估计值。如果提供哈希,则选择提供多少。如果要求Git提供哈希,则仍然可以选择提供多少,使用
--abbrev=number
。请注意,绝对最小值为4:
Git log abc
不会处理
abc
作为散列ID,但是
git log abcd
abcd
视为一个缩写的散列ID。还有一个非常古老的默认值,从git的1.7天开始,是7个字符。)

第一位是非常基本的数学,只是[字母表的大小]^[字符数]因此,
16^length
。不过,任何度量都可能必须从源代码中挖掘出来。它可能的重复实际上只是一点数学问题。git内部只使用长散列,短散列的冲突无关紧要。请参阅
git checkout
将散列视为一个
树型
,因此您应该计算n的数量在blob对象上,以近似任何给定哈希子集和对象数的可能冲突数。有多少树取决于许多因素:一组密集的路径名每次提交都会生成更多的树,但如果提交中的更改很少,并且仅限于一个子树,则这些树中的许多树将被共享罗斯有很多承诺。。。
$ git checkout 2334
error: short SHA1 2334 is ambiguous
hint: The candidates are:
hint:   233475fec8 commit 2018-02-14 - Merge pull request #175 in someRepo from someBranch to someOtherBranch
hint:   2334790f05 commit 2018-06-14 - Merge pull request #917 in someRepo from someBranch to yetAnotherBranch
hint:   233415cfa2 tree
hint:   233438d772 tree
hint:   23348a014a tree
error: pathspec '2334' did not match any file(s) known to git