在我的代码库中,为了避免重叠,最长的哈希前缀必须是多少个字符?

14
--abbrev-commit 标志可与 git loggit rev-list 结合使用,以显示提交对象的部分前缀而不是完整的 40 个字符的 SHA-1 哈希。根据 Pro Git 书籍,默认情况下,它使用七个字符,但如果必要,会使它们变长以保持 SHA-1 不含糊性。
此外,短 SHA 至少有四个字符长。同样根据 Pro Git 书籍,
一般来说,八到十个字符足以在项目中保持唯一。
例如,Linux 内核是一个相当大的项目,拥有超过 450k 的提交和 360 万个对象,没有两个对象其 SHA-1 重叠超过前11个字符。
由于防止所有提交对象的前缀哈希的重叠所需的最长前缀长度(在 Linux 内核的情况下为11)是一个表示仓库大小的粗略指标,我想在我的本地存储库中编写程序来确定相应的数量。我该如何做到这一点?

你是指 https://dev59.com/DGMl5IYBdhLWcg3wyJYe#21015031 吗? - Arkadiusz Drabczyk
@ArkadiuszDrabczyk 不完全正确。您提供的链接仅提供了一种确定给定提交哈希前缀可以有多短以避免与某些其他哈希重叠的方法。我正在询问在存储库中所有提交哈希上该数量的最大值。 - jub0bs
1
你不能严格地确定仓库中所需的前缀长度,而不检查所有提交。 原则上,一个仓库可能只有两个提交,在其前39个字符中完全相同。而实际所需的长度可能会随着下一次提交而改变。 - Keith Thompson
@KeithThompson 我知道。我回答中概述的方法会检查所有提交。 - jub0bs
Linux内核默认使用12个字符(显而易见的原因是Linux发明了git,以便对内核进行版本控制)。你很难在12个字符中发生冲突,但你总可以全面检查一组提交的绝对最小值。 - cyphar
1
@cyphar [...] 你总是可以详尽地检查一组提交的绝对最小值 这就是这个想法。看看我的回答。 - jub0bs
2个回答

23
以下Shell脚本在本地存储库中运行时,将打印出需要的最长前缀长度,以防止该存储库的所有前缀哈希值之间出现重叠。
MAX_LENGTH=4;

git rev-list --abbrev=4 --abbrev-commit --all | \
  ( while read -r line; do
      if [ ${#line} -gt $MAX_LENGTH ]; then
        MAX_LENGTH=${#line};
      fi
    done && printf %s\\n "$MAX_LENGTH"
  )

上次编辑这篇答案时,脚本在克隆Git项目仓库时输出“9”,在克隆OpenStack仓库时输出“9”,在克隆Linux内核仓库时输出“11”。


14
Jubob的脚本很棒,已点赞。
如果你想了解最小提交哈希长度的分布情况,可以运行这个单行命令:
git rev-list --abbrev=4 --abbrev-commit --all | ( while read -r line; do echo ${#line}; done; ) | sort -n | uniq -c

对于今天的git项目本身(git-on-git),这将得到类似以下内容:

 1788 4
35086 5
 7881 6
  533 7
   39 8
    4 9

...得到了1788次提交,每个提交可以用一个4个字符的哈希值来唯一表示(或更少,这是Git的最小缩写),还有4个提交需要9/40个字符的哈希值才能唯一选择它们。

相比之下,像Linux内核这样的大型项目今天的分布情况如下:

6179   5
446463 6
139247 7
10018  8
655    9
41    10
3     11

所以,拥有近500万个对象和60万次提交的数据库中,目前有3个提交需要使用11个十六进制数字来将它们与所有其他提交区分开来。


不错。在我尝试的一个repo中,我得到了这样一行:9 1。也就是说,有一个需要长度为9的哈希项。不是2个或更多,而是1个。因此,如果我手动将其缩写为长度为7,那么在检查等操作时就不会出现冲突。这是因为某些其他内部/对象具有不表示提交的sha吗? - Johan Lundberg
1
@johan-lundberg 观察得很好,答案可能可以改进以指出 Git 在这些缩写中提供的不对称性 - 我的 git rev-list 不包括 --objects 选项... 如果它包括,你会看到一些属于 blob 和 tree 的(未缩写的)sha1。当 Git 缩写提交 sha1 时,它也不允许与这些 blob/tree 哈希发生歧义... 因此,尽管长度为9的提交 sha1 对于提交是唯一的,但缩短后将与对象发生冲突 - 尝试 git show <7或8位长度的sha1> - javabrett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接