什么是Git提交ID?

Ank*_*iya 33 git git-svn uniqueidentifier git-commit

如何生成Git提交ID以唯一标识提交?

例: 521747298a3790fde1710f3aa2d03b55020575aa

它是如何工作的?它们只对每个项目都是唯一的吗?或者全球的Git存储库?

Sch*_*ern 48

Git提交ID是关于提交的每个重要事项的SHA-1哈希.我不打算全部列出,但这里重要的是...

  • 内容,所有这些,而不仅仅是差异.
  • 提交日期.
  • 提交者的姓名和电子邮件地址.
  • 记录消息.
  • 先前提交的ID.

更改其中的任何内容并更改提交ID.是的,具有相同属性的相同提交将在不同的计算机上具有相同的ID.这有三个目的.首先,这意味着系统可以判断提交是否已被篡改.它融入了建筑.

其次,只需查看其ID即可快速比较提交.这使得Git的网络协议非常高效.想要比较两个提交,看看它们是否相同?不必发送整个差异,只需发送ID.

第三,这是天才,具有相同ID的两个提交具有相同的历史.这就是为什么先前提交的ID是哈希的一部分.如果提交的内容相同但父项不同,则提交ID必须不同.这意味着在比较存储库(如推送或拉动)时,一旦Git在两个存储库之间找到共同提交,它就可以停止检查.这使得推拉非常有效.例如...

origin
A - B - C - D - E [master]

A - B [origin/master]
Run Code Online (Sandbox Code Playgroud)

网络对话git fetch origin是这样的......

  • local 嘿起源,你有什么分支?
  • origin 我在E大师
  • local 我没有E,我有你的主人在B.
  • originB你说?我有B,它是E的祖先.检查出来.让我发给你C,D和E.

这也是为什么当您使用rebase重写提交时,其后的所有内容都必须更改.这是一个例子.

A - B - C - D - E - F - G [master]
Run Code Online (Sandbox Code Playgroud)

假设您重写D,只是为了稍微改变日志消息.现在D不再是D,它必须被复制到我们称之为D1的新提交.

A - B - C - D - E - F - G [master]
         \
          D1
Run Code Online (Sandbox Code Playgroud)

虽然D1可以将C作为其父级(C不受影响,提交不知道他们的孩子),但它与E,F和G断开连接.如果我们将E的父级更改为D1,则E不能再为E. 必须将其复制到新的提交E1.

A - B - C - D - E - F - G [master]
         \
          D1 - E1
Run Code Online (Sandbox Code Playgroud)

等等F到F1和G到G1.

A - B - C - D - E - F - G
         \
          D1 - E1 - F1 - G1 [master]
Run Code Online (Sandbox Code Playgroud)

它们都具有相同的代码,只是不同的父代(或者在D1的情况下,是不同的提交消息).

  • 我喜欢这个图形解释,完美的“另一半”是@JustinHoward 的答案,下面向您展示了重现哈希的确切步骤,所以现在您知道了一切、目的和细节! (4认同)
  • 最后提交的 ID。Git 就像区块链。 (2认同)

Jus*_*ard 23

您可以通过运行确切地了解生成提交ID的内容

git cat-file commit HEAD
Run Code Online (Sandbox Code Playgroud)

它会给你一些类似的东西

tree 07e239f2f3d8adc12566eaf66e0ad670f36202b5
parent 543a4849f7201da7bed297b279b7b1e9a086a255
author Justin Howard <justin.howard@example.com> 1426631449 -0700
committer Justin Howard <justin.howard@example.com> 1426631471 -0700

My commit message
Run Code Online (Sandbox Code Playgroud)

它给你:

  1. 树内容的校验和
  2. 父提交ID(如果这是合并,将有更多父母)
  3. 提交时间戳的作者
  4. 提交的提交者带有时间戳
  5. 提交消息

Git接受了所有这些,并对它进行了sha1哈希.您可以通过运行来重现提交ID

(printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) | sha1sum
Run Code Online (Sandbox Code Playgroud)

首先打印字符串commit后跟空格和cat-file文本blob 的字节数.然后它将cat-fileblob 添加到后跟空字节.所有这一切都将贯穿始终sha1sum.

如您所见,此信息中没有任何标识项目或存储库的信息.这不会导致问题的原因是因为两个不同的提交哈希在天文学上不太可能发生冲突.

  • 这确实很好地补充了所选的答案,我已经检查了一下,shell脚本确实有效,我想这是从实际代码中复制的,对吗? (2认同)
  • @JeanVincent:它并不完全来自代码。我想这是用 C 编写的。但它准确地重现了算法(截至目前,但贡献者正在努力替换 SHA1)。 (2认同)