从技术上讲,您不能修改 任何 提交。即使git commit --amend 也不这样做。请记住,每个提交都由其哈希 ID 唯一标识。
你可以做的是获取一些现有的提交,提取它,然后用它来构建一个新的,不同的提交,几乎与原始提交相同,但无论您认为有什么缺陷,都已修复。然后,你必须说服所有人——你自己,以及任何克隆了提交的人——停止使用旧的、有缺陷的提交,而改用闪亮的新提交。新的提交有一个新的、不同的哈希 ID。
如果闪亮的新提交不是在分支的顶端——如果它向后退了两步,例如在这种情况下——那么你有一个额外的问题。请记住,像 master 和 develop 这样的分支名称标识 一个特定的提交,Git 将其称为分支的 tip 提交。每个提交还包含其 父(上一个)提交的哈希 ID,这就是 Git 如何从最新的提交中找到更早的提交:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
在这里,大写字母代表丑陋的散列 ID。名称master 标识提交G:master 的提示。名称develop 标识提交K,develop 的尖端。从提交G,Git 可以向后工作到F,然后是E,依此类推。从K,Git 可以向后工作到J,最终到E 等等。
如果提交 I 有问题,你可以做的是让 Git 提取提交 I,对 index-and-work-tree 对进行一些更改(就像你对任何其他提交所做的那样),然后进行 new 提交——我们称它为 I' 以表明它是 I 的替代品——其父级与 I 的父级相同:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I' <-- temporary
完成后,我们现在只需要将J 复制到一个闪亮的新J',其父级为I',其对I' 的影响与J 对@ 的影响相同987654348@:
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I'-J' <-- temporary
现在我们重复 K 的技巧来生成 K':
...--D--E--F--G <-- master
\
H--I--J--K <-- develop
\
I'-J'-K' <-- temporary
最后,我们告诉 Git:删除临时名称。命名 develop 标识闪亮的新提交 K' 而不是 icky old K。 这给了我们:
...--D--E--F--G <-- master
\
H--I--J--K [abandoned]
\
I'-J'-K' <-- develop
如果我们停止绘制废弃的分支,它看起来好像我们以某种方式更改了三个提交。但我们没有:新的提交有新的、不同的哈希 ID。
...--D--E--F--G <-- master
\
H--I'-J'-K' <-- develop
这就是git rebase -i 所做的。听起来工作量很大,在某些情况下确实如此,但通常git rebase -i 会让您轻松无痛。
请注意,如果您已将develop 推送到其他地方,您现在必须强制-推送此新开发,以告知收到提交I、J 和@987654363 的其他Git @ 它应该忘记那些提交(以及任何以后的提交!),而是使用闪亮的新替代品。
如果其他用户选择了原始的I-J-K 序列,您必须说服他们 也放弃他们的 I-J-K 副本。如果他们在K 上构建了自己的提交,您必须让他们在您闪亮的新K' 上复制他们的旧提交。对于所有其他用户来说,这可能是相当大的工作量,因此请确保您确实想对他们这样做。