【问题标题】:Git: how to modify the content (not commit message) for the HEAD^^ commitGit:如何修改 HEAD^^ 提交的内容(不是提交消息)
【发布时间】:2018-07-17 07:54:22
【问题描述】:

假设我从事以下工作:

  • 功能 1:文件 1 + 文件 3
  • 功能 2:文件 2

我有以下提交

  • 提交 2:功能 2 已完成。
  • 提交 1:功能 1 已完成。

我犯的错误是我忘记将file3添加到commit 1。如何将file3的更改添加到commit 1?

一种方法是:

git reset --soft Commit 1
git add file3
git commit --amend 
git add file2
git commit -m "feature 2 completed"

我不想要这种方式是因为实际上我可能不仅有提交 2,而且还有提交 3,4,5,6...

还有其他简单的方法吗?

谢谢

【问题讨论】:

  • git rebase --interactive 是您需要的命令。但只有当您要更改的历史记录是线性的(即没有合并)时,它才会产生您期望的结果。
  • 感谢@axias,我之前确实找到了 git rebase -i 但不知道在这种情况下如何选择 p/r/e/s/f/x/d 的东西。你介意提供一个例子吗?
  • @axiac 在交互式变基时如何更改提交内容?
  • git rebase的文档中有说明。您还可以阅读this answer,它解释了如何使用 GUI Git 客户端遵循文档中提供的配方。它解释了如何拆分提交,但概念相同:您可以使用git rebase -i修改过去创建的提交。

标签: git git-commit git-amend


【解决方案1】:

从技术上讲,您不能修改 任何 提交。即使git commit --amend 也不这样做。请记住,每个提交都由其哈希 ID 唯一标识。

可以做的是获取一些现有的提交,提取它,然后用它来构建一个新的,不同的提交,几乎与原始提交相同,但无论您认为有什么缺陷,都已修复。然后,你必须说服所有人——你自己,以及任何克隆了提交的人——停止使用旧的、有缺陷的提交,而改用闪亮的新提交。新的提交有一个新的、不同的哈希 ID。

如果闪亮的新提交不是在分支的顶端——如果它向后退了两步,例如在这种情况下——那么你有一个额外的问题。请记住,像 masterdevelop 这样的分支名称标识 一个特定的提交,Git 将其称为分支的 tip 提交。每个提交还包含其 (上一个)提交的哈希 ID,这就是 Git 如何从最新的提交中找到更早的提交:

...--D--E--F--G   <-- master
         \
          H--I--J--K   <-- develop

在这里,大写字母代表丑陋的散列 ID。名称master 标识提交Gmaster提示。名称develop 标识提交Kdevelop 的尖端。从提交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 推送到其他地方,您现在必须强制-推送此新开发,以告知收到提交IJ 和@987654363 的其他Git @ 它应该忘记那些提交(以及任何以后的提交!),而是使用闪亮的新替代品。

如果其他用户选择了原始的I-J-K 序列,您必须说服他们 也放弃他们的 I-J-K 副本。如果他们在K 上构建了自己的提交,您必须让他们在您闪亮的新K' 上复制他们的旧提交。对于所有其他用户来说,这可能是相当大的工作量,因此请确保您确实想对他们这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 2014-06-22
    • 2013-05-08
    • 2011-07-09
    • 2011-11-30
    • 2013-01-01
    相关资源
    最近更新 更多