有人可以检查我更改了过去 git 提交的属性吗?

Can someone check I changed the attributes of past git commits?

我需要创建一个 GitHub 存储库,其中每个提交都有较旧的日期。我的意思是我更改了我的本地计算机日期时间(到过去的日期),编写了一些代码,然后使用该日期提交和推送。然后,我可以在我的 GitHub 存储库中看到出现的提交日期是我在本地计算机上进行提交和推送时的假日期。

我的问题是:有没有什么方法可以验证我是否真的伪造了这些日期?我还删除了一些提交和推送(使用 git reset)并使用 git amend 更改了提交的作者姓名。有人可以通过任何方式验证我进行了这些更改吗?

据我所知,git log 是人们可以查看每次提交(我已成功更改)的作者和日期的少数几种方式之一,但是他们有什么办法可以进行更改回购的历史?

警告阅读此问题的其他人:更改代码库的 git 历史并非没有警告,特别是如果其他开发人员也在使用它。因此,如果您有充分的理由更改提交 authors/dates,请确保您的开发人员同事在这个问题上保持一致。

关于git历史

如果其他开发人员在本地检出相同的代码库,并且他们拉取您的更改,他们很可能会注意到冲突的历史记录。

例如,假设我覆盖了最后一次提交,并将作者从其他人更改为我自己:

git commit --amend --reset-author
git push -f

当另一个开发人员拉取时,他们将遇到合并冲突。
他们的 Vim(或其他配置的编辑器)将打开,并询问他们是否要合并。如果它们确实合并,则此消息将是 git 输出到终端的(部分)内容:

 + ed36af4...fbe3f7f main       -> origin/main  (forced update)

如果没有人检出被篡改的分支,那么任何人都不会注意到历史更改。

找出篡改的其他方法

以上,我正在手挥一些侦探工作。举个人为的例子,如果您将提交日期更改为发明 git 之前,那么人们就会知道 git 历史已被篡改。作为一个不太人为的例子,如果您更改 git 作者,使他们无法访问该存储库,那么这就是篡改的证据。 (“咦,Sara 2017 年没在这里工作,她怎么能访问这个私人仓库?!”

请注意,除了 git 历史之外,回购还有其他方式 protected/monitored/audited。如何实现这一点是另一个问题的另一个主题。但一个非常简单的方法是定期备份 git 存储库。

这里是要知道的:

  • 一个提交是一个编号实体,由数据(源快照)和元数据(作者姓名和电子邮件和 date-stamp、提交者三元组、parent 哈希 ID、任何其他内部 headers、parent 行等等,然后是空行和提交消息 subject-and-body).

  • 数据——源快照——实际上存储为单个元数据行,树<em>hash-id</em>.因此,源快照是间接的,这就是存储 相同 源快照的两次提交实际上不会将源快照存储两次的方式。例如,如果您使用树 T1 提交 C1,然后创建具有新树的新提交 C2,然后还原提交 C2 以创建提交 C3,则提交 C3 中的树与 C1 中的树相同。

  • 提交的 哈希 ID 是(整个)元数据的加密校验和,包括附加到消息的任何提交签名 body .有关更多详细信息,请参阅 How does commit signing work?

  • 目前,此加密校验和使用 has been broken 的 SHA-1。然而,现有的破解 SHA-1 的技术非常昂贵(无论是美元还是您当地的任何货币,以及计算时间)并且会留下明显的痕迹。

每当有人进行提交时,他们控制所有元数据,因此无法判断该新提交是否包含准确的元数据(“是的,我的名字真的是 Zaphod Beeblebrox,我今天早上合法地更改了它”)或不包含(“我撒谎了,我的法定名字实际上是 Jean Baptiste Emmanuel Zorg”)。但是如果有人要获取现有提交并尝试修改它,他们将得到的不是修改后的提交,而是另一个 新提交,具有新的和不同的 SHA-1 哈希ID。获得 re-uses 旧哈希 ID 的新提交的唯一方法是使用 SHA-1 破解技术,这将留下明显的痕迹。

提交自己 历史,并形成一种 Merkle Tree,因为每个提交都持有其 parent 的哈希 ID提交。只是我们(人类)和 Git 本身,通常 find 通过使用 分支名称 来提交,它被定义为name1 持有可更改的哈希 ID。只要有人有权以该名称存储新的不同哈希 ID,如果我们信任 名称,我们就会看到最新的哈希 ID。

这反过来意味着,如果您真正关注/使用哈希 ID,而不是简单地依赖于一些可变的分支名称,您会注意到任何人“摆弄历史”,无论其物理程度如何值得注意的(即,你必须有一些提交 X 才能看到其他人已经提出了一些不同的哈希 ID Y 来使用X,然后由于 Merkle-tree 问题也更改了每个后续提交)。

Git 标签也可以签名(使用 GPG 签名或等效签名)。这些数字签名方法——无论是用于单个提交,还是仅用于一系列提交末尾的标签——都可以使用 more-secure 加密而不是 SHA-1。 Git 本身也被修改为使用 SHA-256,如果没有别的,它至少有更多的 ,使得用于破解 SHA-1 的技术不太有效。


1具体来说,分支名称refs/heads/[=形式的名称41=]分支机构</em>。前导 refs/heads/ 部分使其成为分支名称。如果前导部分是refs/tags/,名称是标签名称。其他名字住在 refs/ name-space 的不同部分。特殊名称——HEADORIG_HEADMERGE_HEAD 等——位于 otherwise-required 顶级 refs/ 限定符之外。