44

我发现很难理解 Git 如何创建完全唯一的哈希,即使在前 4 个字符中也不允许相同。我只能使用前四个字符在 Git Bash 中调用提交。算法中是否特别决定了第一个字符是“超”唯一的并且永远不会与其他类似的散列冲突,或者算法是否以相同的方式生成散列的每个部分?

4

2 回答 2

69

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 的可能性很大。

于 2016-01-13T10:44:50.923 回答
9

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 年第四季度),“ sha1to 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_id oid并且应该准备好处理非 SHA1 对象 ID。将其重命名为abbrev_oid_in_line().

wt_status_get_detached_from()提到“sha1”的一些评论。他们引用的变量在e86ab2c1cd中重命名(“wt-status: convert to struct object_id",2017-02-21, Git v2.13.0-rc0)。更新注释以引用“ oid”。

于 2017-04-09T21:26:00.163 回答