一般认为,在一个给定的代码库中唯一标识一个变化是多less?

如果你打算build立一个目录结构,在Git仓库中为一个提交命名一个目录,并且你希望它足够短以使你的眼睛不stream血,但是足够长,以至于碰撞的机会会忽略不计,通常需要多lessSHA子串?

比方说,我想唯一识别这个变化: https : //github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920

我可以使用前四个字符: https : //github.com/wycats/handlebars.js/commit/e629

但是我觉得这样做会很危险。 但是如果使用一个代码库,那么在几年之后,如果我使用8个字符,可能会有30k的变化,那么碰撞的可能性有多大? 12? 有这样一个普遍认为可以接受的数字吗?

这个问题实际上是在Pro Git书的第7章中回答的:

一般来说,八到十个字符在项目中足够独特。 最大的Git项目之一,Linux内核,开始需要可能的40个中的12个字符来保持独特性。

7位数字是短SHA的Git默认值,所以对于大多数项目来说都没问题。 如上所述,内核团队多次增加了他们的工作,因为有数十万次提交。 所以对于你的30k的提交,8或10位数字应该是完美的。

注意:你可以问git rev-parse --short最短但唯一的SHA1。
请参阅“ 从常规哈希获取短哈希 ”

 git rev-parse --short=4 921103db8259eb9de72f42db8b939895f5651489 92110 

正如你在我的例子中看到的那样,即使我指定长度为4,SHA1的长度也是5。


对于大的回购,自2010年以来,7是不够的,由Linus Torvalds本人(git 1.7.4.4,2010年10月) 承诺dce9648 :

7的默认值来自git开发的早期,当七个hex数字是很多(它涵盖了大约250多万散列值)。
那时候我以为65K的修改是很多的(这是我们打算在BK里面打的),每个版本都会有5-10个左右的新东西,所以一百万个物体是一个很大的数字。

(BK = BitKeeper)

现在,内核甚至不是最大的git项目,甚至内核也有大约22万个版本(比BK树大得多),我们正在接近200万个对象。
在那个时候,七个hex数对于它们中的许多来说仍然是唯一的,但是当我们谈论对象的数量和散列大小之间仅仅两个数量级的差异时,在截断的散列值中将会发生冲突。
它不再是不切实际的 – 它总是发生。

我们应该增加一个不切实际的小默认缩写, 并且为人们在gitconfiguration文件中设置他们自己的默认每个项目添加一个方法

 core.abbrev 

设置长度的对象名称缩写为。
如果未指定,许多命令缩写为7hex,这可能不足以使缩写的对象名称在足够长的时间内保持唯一。

environment.c

 int minimum_abbrev = 4, default_abbrev = 7; 

注意:正如下面的marco.m所述 , core.abbrevLenghtcore.abbrev中被重命名为git 1.7.4.4,在commit a71f09f

core.abbrevlength重命名为core.abbrev

--abbrev=$n对应于--abbrev=$n命令行选项。


最近,Linus又添加了e6c587c (对于Git 2.11,2016年第四季):
(正如Matthieu Moy的回答所提到的)

在相当早的时候,我们决定把对象名称缩写成7-hexdigits,但是随着项目的增长,越来越多的人看到在早些时候做出这样一个简短的对象名称,并且logging在日志消息中不再是唯一的。

目前Linux内核项目需要11到12个hex数,而Git本身需要10个hex数来唯一标识它们拥有的对象,而许多较小的项目可能仍然是原来的7-hexdigit默认值。 单一尺寸不适合所有项目。

引入一种机制,在这种机制下,我们根据首次请求使用默认设置缩写对象名称的方式来估计存储库中对象的数量,并为存储库提供了一个合理的默认值。 基于期望在使用缩短到前N位的对象名称时,在具有2^(2N)对象的存储库中看到冲突,请使用足够数量的hex数来覆盖存储库中对象的数量。
我们添加到缩写名称的每个hex数(4位)允许我们在存储库中拥有四倍(2位)的对象。

参见Linus Torvalds( torvalds )的提交e6c587c (2016年10月1日) 。
见Junio C gitstergitster ) 提交的65acfea (2016年10月1日)的提交7b5b772 。
(由Junio C gitster合并- gitster – in commit bb188d0 ,2016年10月3日)

这个新属性(猜测SHA1缩写值的合理默认值)直接影响到Git如何计算它自己的发布版本号 。

这被称为生日问题。

对于小于1/2的概率,碰撞概率可近似为

p〜=(n 2 )/(2m)

其中n是项目的数量,m是每个项目的可能性数量。

hexstring的可能性数是16 c ,其中c是字符数。

所以对于8个字符和30K提交

30K〜= 2 15

(2 1 )/(2 * 16 8 )= 2 30/2 33 = 1

增加到12个字符

2 )/(2 * 16 12 )= 2 30/2 49 = 2 -19

这个问题已经得到解答,但是对于任何寻找math背后的人来说 – 这就是所谓的生日问题 ( 维基百科 )。

这是关于有2个(或更多)来自N人群的人在同一天生日的可能性。 这与类似于2个(或更多)git提交可能类似于具有总共N个提交具有相同的长度为X的哈希前缀的仓库。

看看概率表 。 例如,对于长度为8的散列hexstring,当存储库只有大约9300个项目(git提交)时,碰撞概率达到1%。 对于11万次提交,概率是75%。 但是如果你有长度为12的哈希hexstring,在100 000次提交中发生碰撞的概率低于0.1%。

Git版本2.11(或者可能是2.12?)将包含一个function,可以将短标识符(例如git log --oneline )中使用的字符数量与项目大小相git log --oneline 。 一旦你使用这样的版本的Git,你的问题的答案可以是“select任何长度的Git给你的git log --oneline ,这是足够安全的”。

有关更多详细信息,请参阅更改“core.abbrev”的默认值? 在Git Rev News第20期讨论并提交bb188d00f7 。