在我的仓库中,最长的哈希前缀必须多长时间才能防止任何重叠?
Posted
技术标签:
【中文标题】在我的仓库中,最长的哈希前缀必须多长时间才能防止任何重叠?【英文标题】:In my repo, how long must the longest hash prefix be to prevent any overlap? 【发布时间】:2015-12-01 01:50:10 【问题描述】:--abbrev-commit
标志可以与git log
和git rev-list
结合使用,以显示部分前缀而不是提交对象的完整 40 个字符的 SHA-1 哈希。根据Pro Git book,
它默认使用七个字符,但如果需要使它们更长,以保持 SHA-1 明确[...]
此外,短 SHA 至少有 4 个字符长。还是按照 Pro Git 的书,
通常,八到十个字符足以在项目中保持唯一性。
例如,Linux 内核是一个相当大的项目,有超过 45 万次提交和 360 万个对象,没有两个对象的 SHA-1 重叠超过前 11 个字符。
由于防止提交对象的所有前缀哈希之间发生任何重叠所需的最长前缀的长度(在 Linux 内核的情况下为 11)是 repo 大小的粗略指标,我想以编程方式确定我自己的本地存储库中的相应数量。我该怎么做?
【问题讨论】:
你的意思是***.com/a/21015031/3691891? @ArkadiuszDrabczyk 不完全是。您的链接仅提供了一种方法来确定给定提交哈希的前缀有多短,以避免与其他哈希重叠。我要求存储库中所有提交哈希的最大数量。 如果不检查 repo 中的所有提交,就无法严格确定所需的前缀长度。原则上,一个 repo 只能有两个前 39 个字符相同的提交。实际需要的长度可能会随着下一次提交而改变。 @KeithThompson 我知道。我的回答中概述的方法确实检查了所有提交。 @cyphar [...] 你总是可以详尽地检查一组提交的 absolute 最小值是多少。 就是这样。看看我的回答。 【参考方案1】:以下 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"
)
上次我编辑这个答案时,脚本打印出来了
“9”在Git-project repo 的克隆中运行时, “9”在OpenStack repo 的克隆中运行时, “11”在Linux-kernel repo 的克隆中运行时。【讨论】:
【参考方案2】:Jubob 的剧本很棒,点赞。
如果你想了解 minimum-commit-hash-length 的分布,你可以运行这个单行:
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 个哈希字符才能唯一选择它们。
相比之下,像Linux kernel 这样更大的项目今天具有以下分布:
6179 5
446463 6
139247 7
10018 8
655 9
41 10
3 11
因此,对于一个包含近 500 万个对象和 600k 次提交的数据库,目前有 3 个提交需要 40 个十六进制数字中的 11 个才能将它们与所有其他提交区分开来。
【讨论】:
以上是关于在我的仓库中,最长的哈希前缀必须多长时间才能防止任何重叠?的主要内容,如果未能解决你的问题,请参考以下文章