【问题标题】:What is a Git commit ID?什么是 Git 提交 ID?
【发布时间】:2015-05-20 08:21:27
【问题描述】:

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

示例:521747298a3790fde1710f3aa2d03b55020575aa

它是如何工作的?它们仅对每个项目都是独一无二的吗?还是用于全球的 Git 存储库?

【问题讨论】:

标签: git git-svn uniqueidentifier git-commit


【解决方案1】:

Git 提交 ID 是关于提交的所有重要事项的 SHA-1 hash。我不会一一列举,但这里是重要的...

  • 内容,所有内容,而不仅仅是差异。
  • 提交日期。
  • 提交者的姓名和电子邮件地址。
  • 日志消息。
  • 上一次提交的 ID。

更改其中任何一项,提交 ID 都会更改。是的,具有相同属性的相同提交将在不同的机器上具有相同的 ID。这有三个目的。首先,这意味着系统可以判断提交是否被篡改。它直接融入架构中。

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

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

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

A - B [origin/master]

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

  • local嘿起源,你有哪些分店?
  • origin我在E有硕士。
  • local我没有E,我有你在B的师父。
  • originB 你说什么?我有 B,它是 E 的祖先。让我把 C、D 和 E 发给你。

这也是为什么当你用 rebase 重写一个提交时,它之后的一切都必须改变。这是一个例子。

A - B - C - D - E - F - G [master]

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

A - B - C - D - E - F - G [master]
         \
          D1

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

A - B - C - D - E - F - G [master]
         \
          D1 - E1

以此类推,F 到 F1,G 到 G1。

A - B - C - D - E - F - G
         \
          D1 - E1 - F1 - G1 [master]

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

【讨论】:

  • 最后一次提交的 ID。 Git就像区块链。?
  • 我喜欢这个图形化的解释,完美的“另一半”是来自@JustinHoward 的答案,下面向您展示了重现哈希的确切步骤,所以现在您知道了一切、目的和详细!
【解决方案2】:

您可以通过运行准确查看生成提交 ID 的内容

git cat-file commit HEAD

它会给你类似的东西

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

它给你:

  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

首先打印字符串commit,后跟一个空格和cat-file 文本块的字节数。然后它将cat-file blob 添加到后面跟一个空字节。然后所有这些都通过sha1sum 运行。

如您所见,此信息中没有任何内容可以识别项目或存储库。这不会导致问题的原因是因为从天文数字上讲,两个不同的提交哈希发生冲突的可能性很小。

【讨论】:

  • 这很好地补充了选择的答案,我已经检查过了,shell脚本确实有效,我猜这是从实际代码中复制的,对吧?
  • @JeanVincent:它并没有完全取自代码。我想那是用 C 语言编写的。但它准确地再现了算法(截至目前,贡献者正在努力替换 SHA1)。
猜你喜欢
  • 1970-01-01
  • 2018-03-20
  • 2016-11-09
  • 1970-01-01
  • 2016-06-12
  • 2015-01-28
相关资源
最近更新 更多