我发现很难理解 Git 如何创建完全唯一的哈希,即使在前 4 个字符中也不允许相同。我只能使用前四个字符在 Git Bash 中调用提交。算法中是否特别决定了第一个字符是“超”唯一的并且永远不会与其他类似的散列冲突,或者算法是否以相同的方式生成散列的每个部分?
2 回答
Git 使用以下信息来生成 sha-1:
- 提交的源树(分解为所有子树和 blob)
- 父提交 sha1
- 作者信息(带时间戳)
- 提交者信息(对,那些是不同的!,也有时间戳)
- 提交消息
(关于完整的解释;看这里)。
Git不保证前 4 个字符是唯一的。在Pro Git Book 的第 7 章中写道:
Git 可以为你的 SHA-1 值找出一个简短的、唯一的缩写。如果您将 --abbrev-commit 传递给 git log 命令,输出将使用较短的值但保持它们唯一;它默认使用七个字符,但如果需要使它们更长,以保持 SHA-1 明确:
因此,Git 只是在必要时使用缩写以保持唯一性。他们甚至注意到:
通常,八到十个字符足以在一个项目中保持唯一性。
例如,Linux 内核是一个相当大的项目,有超过 45 万次提交和 360 万个对象,没有两个对象的 SHA-1 重叠超过前 11 个字符。
因此,实际上它们仅取决于具有完全相同(a 的 X 个第一个字符)sha 的可能性很大。
2017 年 4 月:请注意,在 all shattered.io 事件(谷歌实现 SHA1 冲突)之后,20 字节格式将不会永远存在。
第一步是用一个通用对象替换unsigned char sha1[20]
整个 Git 代码库中的硬代码,该通用对象的定义在未来可能会改变(SHA2?,Blake2,...)
请参阅brian m的提交 e86ab2c(2017 年 2 月 21 日) 。卡尔森 ( bk2204
) .
将 的剩余用途转换
unsigned char [20]
为struct object_id
。
这是从brian m提交 5f7817c(2015 年 3 月 13 日)开始的持续努力的一个例子。carlson ( bk2204
),对于 v2.5.0-rc0,在cache.h
:
/* The length in bytes and in hex digits of an object name (SHA-1 value). */
#define GIT_SHA1_RAWSZ 20
#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
struct object_id {
unsigned char hash[GIT_SHA1_RAWSZ];
};
并且不要忘记,即使使用 SHA1,前 4 个字符也不再足以保证唯一性,正如我在“通常认为需要多少 git sha才能唯一识别给定代码库中的更改? ”中解释的那样。
2017 年 12 月更新Git 2.16(2018 年第一季度):支持替代 SHA 的努力正在进行中:请参阅“为什么 Git 不使用更现代的 SHA? ”。
您将能够使用另一个散列:SHA1 不再是 Git 的唯一散列。
2018-2019 更新:已在 Git 2.19+ 中做出选择:SHA-256。
参见“散列函数转换”。
这尚未激活(意味着 git 2.21 仍在使用 SHA1),但正在编写代码以支持未来的 SHA-256。
使用 Git 2.26(2020 年第一季度),工作继续进行,并使用“结构object_id"
替换使用char *sha1
”
请参阅提交 2fecc48、提交 6ac9760、提交 b99b6bc、提交 63f4a7f、提交 e31c710、提交 500e4f2、提交 f66d4e0、提交 a93c141、提交 3f83fd5、提交 0763671(2020 年 2 月 24 日),作者是Jeff King ( peff
)。
(由Junio C Hamano 合并 -- gitster
--在提交 e8e7184中,2020 年 3 月 5 日)
packfile
: 降低nth_packed_object_sha1()
签字人:杰夫·金
曾几何时,这
nth_packed_object_sha1()
是获取包文件索引位置的 oid 的主要方法。
但是现在我们有了更加类型安全的nth_packed_object_id()
包装器,并且所有的调用者都被转换了。
让我们放弃 "
sha1
" 版本(将更安全的包装器转换为单个函数),这样就没有人想引入新的调用者了。
使用 Git 2.29(2020 年第四季度),“ sha1
to oid
”重命名仍在继续。
请参阅Martin Ågren ( ) 的提交a46d1f7、提交 fb07bd4、提交 cfaf9f0、提交 ef2d554、提交 962dd7e、提交 8f7e3de、提交 b1f1ade(2020 年 9 月 27 日)。(由Junio C Hamano 合并 -- --在提交 07601b5中,2020 年 10 月 5 日)none
gitster
wt-status
: 用 oid 替换 sha1 提及签字人:Martin Ågren
abbrev_sha1_in_line()
使用struct
object_idoid
并且应该准备好处理非 SHA1 对象 ID。将其重命名为abbrev_oid_in_line()
.
wt_status_get_detached_from()
提到“sha1”的一些评论。他们引用的变量在e86ab2c1cd中重命名(“wt-status: convert to structobject_id",
2017-02-21, Git v2.13.0-rc0)。更新注释以引用“oid
”。