在我的回购协议中,最长的哈希前缀必须有多长才能防止重叠?

In my repo, how long must the longest hash prefix be to prevent any overlap?

--abbrev-commit 标志可以与 git loggit rev-list 结合使用,以显示部分前缀而不是提交对象的完整 40 个字符的 SHA-1 哈希值。根据 Pro Git book,

it defaults to using seven characters but makes them longer if necessary to keep the SHA-1 unambiguous [...]

此外,短 SHA 的长度至少为 4 个字符。还是按照亲Git书上的,

Generally, eight to ten characters are more than enough to be unique within a project.

As an example, the Linux kernel, which is a pretty large project with over 450k commits and 3.6 million objects, has no two objects whose SHA-1s overlap more than the first 11 characters.

由于防止提交对象的所有前缀哈希之间出现任何重叠所需的最长前缀的长度(11,在 Linux 内核的情况下)是回购大小的粗略指标,我'我想以编程方式确定我自己的本地存储库中的相应数量。我该怎么做?

以下 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"
  )

我上次编辑这个答案时,打印了脚本

Jubob 的剧本很棒,点赞。

如果你想了解最小提交哈希长度的分布,你可以运行这一行:

git rev-list --abbrev=4 --abbrev-commit --all | ( while read -r line; do echo ${#line}; done; ) | sort -n | uniq -c

对于今天的 git project 本身 (git-on-git),这会产生如下内容:

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

... 产生 1788 提交,可以用 4-char 散列(或更低,这是 Git 的最小缩写)和 4 提交需要 9-of-40 个哈希字符才能唯一地 select他们。

相比之下,Linux kernel 等更大的项目今天有这样的分布:

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

因此,对于包含近 500 万个对象和 60 万次提交的数据库,3 次提交目前需要 40 个十六进制 digit 中的 11 个来将它们与所有其他提交区分开来提交。