`git commit --amend` 是否触及了不必要的文件?

Is `git commit --amend` touching more files than is necessary?

我经常遇到以下情况:

  1. 修改文件 A、B 和 C。
  2. 使用 git commit 提交修改。
  3. 构建项目,因此构建是最新的。
  4. 仅对文件 A 进行后续/修复修改。
  5. 运行git commit -a --amend(或git commit --amend path/to/A
  6. 逐步重建项目。

现在,由于自上次构建以来我只修改了文件 A,因此我希望只重建文件 A,但我总是看到 A、B 和 C (即,整个提交涉及的所有文件)都被重建。

在我看来,git commit --amendtouching / bumping 每个 A、B 和 C 的最后修改时间戳,即使我只是将 A 的修改添加到提交。

有这个必要吗?能不能避免,只碰A只重建A?

如果重要的话,我的项目是 C++ 的,我的构建系统是 cmake+ninja,但我认为这在很大程度上不是重点,因为构建系统依赖上次修改的时间戳来确定要重建的内容是相当标准的。

避免这种情况(手动)的一种方法是在不修改的情况下完成所有提交,并且在完成更改后,rebase interactively 压缩提交(您现在正在修改的提交)

git commit 不会触及工作树中的 any 文件。这里用--amend没关系

没有 -agit commit 也不会 使用 工作树中的任何文件,但是 git commit -a 有 Git,实际上,运行 git add -u 首先,它将 读取 工作树中的一些文件,以便将它们复制到索引中。然后,无论哪种方式——有或没有 -a——git commit 从索引中的任何内容构建新提交。

新的提交一旦完成,就会有一些新的、独特的、前所未见的哈希 ID。如果你正在做一个普通的 git commit(没有 --amend),你的存储库中有一些提交系列,每个都有自己唯一的哈希 ID,last 这样的提交有一些哈希 ID H:

... <-F <-G <-H   <-- your-branch (HEAD)

(这里,大写字母代表实际的原始哈希 ID,它看起来是随机的,但实际上不是,但也不可预测。)新提交获取其新的唯一哈希 ID I,在I里面,存储的父哈希ID是H。 Git 将新 ID 写入分支名称,给出:

...--F--G--H--I   <-- your-branch (HEAD)

--amend 不同之处在于,Git 不是让新提交 I 指向现有提交 H,而是使用 [= 构造新提交58=]与 H 具有相同的 父级,在本例中为 G。结果是 H 被推到一边:

          H
         /
...--F--G--I   <-- your-branch (HEAD)

现有提交 H 未更改,但它似乎消失了:从 I 开始并向后工作无法找到它。所以git log把它隐藏了,好像就没了,就好像Git不知怎么变了H一样。 Git 没有; H 仍然完好无损。默认情况下,它仍然可以恢复至少 30 天,因为哈希 ID 存储在 Git 称为 reflogs 的地方。但它 看起来 不见了。

如果您看到各种文件被重建,这不是因为 Git 本身触及了源文件。其他东西可能触及了源文件,或者——我的猜测,但只是猜测——你的构建系统可能将它们标记为依赖于特定的 Git 提交哈希:因为 IH,构建工件是 H 而不是 I 的结果,它们现在已经过时了。

(当然,其他可能性包括 Git 更改文件时间戳的挂钩。)