什么是Git提交ID?

什么是Git提交ID?,git,git-svn,uniqueidentifier,git-commit,Git,Git Svn,Uniqueidentifier,Git Commit,如何生成Git提交id来唯一标识提交 示例:521747298A3790FDE1710F3AA2D03B5020575AA 它是如何工作的?它们是每个项目唯一的吗?或者对于全球范围内的Git存储库?Git提交ID是关于提交的每一件重要事情的。我不打算一一列举,但这里有一些重要的 内容,全部,而不仅仅是差异 提交日期 提交人的姓名和电子邮件地址 日志消息 上一次提交的ID 如果更改其中任何一项,则提交ID将更改。是的,具有相同属性的相同提交将在不同的计算机上具有相同的ID。这有三个目的。首先,

如何生成Git提交id来唯一标识提交

示例:
521747298A3790FDE1710F3AA2D03B5020575AA


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

Git提交ID是关于提交的每一件重要事情的。我不打算一一列举,但这里有一些重要的

  • 内容,全部,而不仅仅是差异
  • 提交日期
  • 提交人的姓名和电子邮件地址
  • 日志消息
  • 上一次提交的ID
如果更改其中任何一项,则提交ID将更改。是的,具有相同属性的相同提交将在不同的计算机上具有相同的ID。这有三个目的。首先,这意味着系统可以判断提交是否被篡改。它直接融入到建筑中

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

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

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

A - B [origin/master]
git fetch origin
的网络对话如下所示

  • local
    Hey origin,你们有哪些分支机构
  • origin
    我在E有硕士学位
  • local
    我没有E,你的主人在B
  • origin
    B你说呢?我有B,它是E的祖先。我给你寄C、D和E
这也是为什么当您使用rebase重写提交时,它之后的所有内容都必须更改的原因。这里有一个例子

A - B - C - D - E - F - G [master]
假设您重写了,只是为了稍微更改日志消息。现在D不能再是D,它必须被复制到一个新的commit中,我们称之为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的情况下是不同的提交消息)。

通过运行

git cat-file commit HEAD
(printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) | sha1sum
它会给你类似的东西

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
首先打印字符串
commit
,后跟
cat文件的空格和字节计数。然后,它将
cat文件
blob添加到该文件,后跟一个空字节。所有这些都将通过
sha1sum
运行


正如您所看到的,在这些信息中没有标识项目或存储库的内容。这不会引起问题的原因是,两个不同的提交哈希值在天文上不太可能发生冲突。

看,这很好地补充了选择的答案,我已经检查过了,shell脚本确实有效,我猜这是从实际代码复制的,对吗?@JeanVincent:它不是完全从代码中获取的。我想这是用C写的,但它准确地再现了算法(到目前为止,但是贡献者正在努力替换SHA1)。Git就像区块链。我喜欢这个图形化的解释,完美的“另一半”是@JustinHoward的答案,下面是复制散列的确切步骤,所以现在你知道了一切,目的和细节!