【问题标题】:How can I create a commit with a new SHA in git?如何在 git 中使用新的 SHA 创建提交?
【发布时间】:2025-12-20 11:20:18
【问题描述】:

我需要在 Git 中创建一个具有不同 SHA 的等效提交对象。所有提交都经过 GPG 签名。我知道我可以更改作者+提交时间戳,但分辨率只有一秒,并且我们不允许偏离系统时钟超过一秒。我也无法更改提交消息、作者/提交者姓名和电子邮件和/或用于签署提交的密钥。我可以更改提交的哪些其他字段以获得不同的提交消息?


动机:我们正在使用一个内部工具,如果两个属性引用同一个提交,由于某种原因它不起作用,即使我们是故意设置它。

【问题讨论】:

  • 时区偏移量?
  • This gist 包含关于提交 ID 的几乎所有详细信息。
  • 看来改内部工具会更方便。

标签: git commit gnupg sha


【解决方案1】:

这个问题的技术答案是这样的:

散列后的数据包括:

  • 您无法控制的标头(无论如何,它源自我将要提到的其他数据)
  • 提交的 TREE 对象哈希 - 提交内容的反映
  • COMMIT 对象哈希
  • 作者姓名、电子邮件、时间戳
  • 提交者姓名、电子邮件、时间戳
  • 提交消息

改变TREE 可能会扩展“等效”提交的定义。您已明确排除更改提交消息或作者/提交者信息。剩下的选项是提交父列表,但这是否有意义取决于你在做什么。

因此,由于选项有限,让我们快速看一下其中的每一个(即使是那些似乎被排除在外的选项):

TREE object:这唯一地表示内容 - 即您将在工作树中的哪些路径的哪些文件中看到哪些数据。乍一看,这似乎是必须保持不变才能满足“等效提交”的最基本定义的东西。当然,任何更改——无论多么小,无论工作树中的哪个位置——都会改变哈希,所以也许你可以插入一个专门用于随机数值的文件或目录来改变哈希?

作者或提交者信息:首先要考虑的是:不触摸姓名的要求有多敏感?你能在名字的末尾加上一个不可见的字符就可以了,还是必须逐位匹配?

或者,那些时间戳......说你不能改变系统时钟,当提交时间戳被定义为引用提交创建时间时,除非你试图创建几个等效的提交,否则似乎很迂腐一次。即使您同时需要两个,您也应该能够做到这一点而不会超出您的容忍度。

提交信息:同样,不改变这一点的要求有多严格?你能用换行符,或者至少是一个不可见的字符吗?

家长提交:如果您仍然对以上所有内容束手无策,那么剩下的就是这些了。这真的归结为,for 的提交是什么?重复提交是否将具有相同的父级?

P -- A
 \
  A'

在这种情况下,你真的不能在这里做任何事情。但或者,如果它是提交的并行树:

P -- A

P' -- A'

好吧,那么您需要做的就是在每棵树上植入一个在某些方面有所不同的根提交。例如,提交诸如“Root commit 1”、“Root commit 2”之类的消息?

【讨论】:

  • 签名存储在哪里?
  • 据我所知,签名与它签名的对象一起存储在 git 数据库中。这可能在一个松散的对象中(.git/objects/01/23456789012345678901234567890123456789),也可能在一个包文件中(1.git/objects/pack/...`)