【问题标题】:Edit a specific commit and reapply subsequent commits编辑特定提交并重新应用后续提交
【发布时间】:2021-07-22 13:59:36
【问题描述】:

我目前正在提交开源代码,提交的结构非常严格。我有三个提交,我们称它们为 A、B 和 C。重要的是要注意所有更改都在同一个文件中。

此外,我在所有三个提交中都收到了有关代码的反馈。是否可以进入暂存代码,例如提交 B,编辑几行代码,重新提交,然后重新应用 C,而不会有太多麻烦?

我现在能想到的最好方法是撤消所有三个提交,然后再次执行块暂存,这需要时间才能变得完美,因为一些代码就在附近。

【问题讨论】:

  • 我认为你想要一个交互式变基。它会为您提供一个提交列表,并允许您根据需要编辑或仅应用每个提交。
  • 类似问题here 具有类似的建议解决方案。可能值得一看。

标签: git github git-commit


【解决方案1】:

无论你如何实现结果,当你完成后,你将不会使用原来的三个提交。如果你被允许 100% 单独离开A,你可以保留原来的A,但如果你必须触摸B,你将不再拥有原来的B,因此必须做一个C 的新副本。

到目前为止,这只是事实陈述,而不是关于如何实现您想要的建议。 想要的方法通常是使用git rebase -i

假设你现在在分支feature

...--o--o--o--o   <-- main
               \
                A--B--C   <-- feature (HEAD)

你只需运行git rebase -i main,Git 就会提供一个指令表,告诉 Git 将三个提交保持原样:

# instructions
pick <hash-of-A> <subject-of-A>
pick <hash-of-B> <subject-of-B>
pick <hash-of-C> <subject-of-C>

将第二个 pick 更改为 edit 并写回指令表并退出您的编辑器。1 Git 现在将尝试直接复制提交 A 开始,这将成功。然后它将继续尝试复制提交B,这也会成功,但现在它将在复制过程中停止:

...--o--o--o--o   <-- main
               \
                A--B   <-- HEAD
                    \
                     C   <-- feature

您将处于分离 HEAD 模式,HEAD 选择提交 B

您现在可以更改要更改的文件git add,然后运行git commit --amend--amend 将让 Git 进行 new 提交——我们称之为 B'——使用提交 A 作为其父级,而不是提交 B。结果如下所示:

...--o--o--o--o   <-- main
               \
                A--B'  <-- HEAD
                 \
                  B--C   <-- feature

您现在可以运行 git rebase --continue 以使 Git 继续执行 pick C 命令。这将挑选提交C,创建一个我们称之为C' 的新提交。 这里可能会发生一些合并冲突,因为cherry-pick实际上是一个合并。如果是这样,您需要修复它们并再次恢复,然后才能提交 C' 但是,如果没有发生冲突,我们现在处于这种状态:

...--o--o--o--o   <-- main
               \
                A--B'-C'  <-- HEAD
                 \
                  B--C   <-- feature

这完成了交互式变基要执行的一组操作,所以它现在执行 any 变基的最后一个技巧,即将分支名称拉到“这里”(无论@987654351 @现在)并重新附加您的HEAD

...--o--o--o--o   <-- main
               \
                A--B'-C'  <-- feature (HEAD)
                 \
                  B--C   [abandoned]

如果您想查看原始提交,它们仍然存在:您只需找到原始提交的哈希 ID C。这适用于:

  • ORIG_HEAD,只是短暂的时间(因为ORIG_HEAD 不断被覆盖);
  • HEAD 的 reflog,默认情况下至少多 30 天;和
  • 分支 feature 的 reflog,默认情况下至少多 30 天。

reflog 条目具有数字后缀名称:feature@{1}。您还可以使用与时间相关的名称,例如 HEAD@{yesterday}。通常,如果某个名称在任何给定时间段内发生了不止一次更改,那么您将希望运行 git reflog,而不是尝试猜测诸如“yesterday.10.am”之类的内容。


1如果您有一个长时间运行的编辑器(emacs、atom 等的一些变体),请使用它必须向等待的 Git 发回这个文件现在已完成的信号,并且Git 应该会恢复。

【讨论】:

  • git rebase -i using edit 正是我想要的。感谢您的解释性回答。
【解决方案2】:

也许吧。

我对 Git 很偏执,所以我总是走得很慢。

  1. 从提交 A 创建一个新分支(我假设是第一次提交)
  2. Git 修改最后一次提交,应该是A,可以更新cmets。你得到了 A' - 它就像 A 一样,但是一个新的提交,因为你改变了它
  3. Git cherry pick 提交 B 到新分支。 Git 修改最后一次提交,它将是 B'(它是樱桃挑选的,所以也是一个新的提交)
  4. Git cherry pick 将 C 提交到新分支。你明白了。

这是一种安全的方法。您的原始提交仍在原始分支上。您的新分支具有相同的逻辑提交,但具有您想要的更改。

将新分支推送到 git hub。使用那个。

【讨论】:

  • 这是在创建指向与现有分支相同的最终提交的新分支名称之后执行git rebase 的手动方法。这种方法没什么问题,只是比使用git rebase -i更工作。
  • 你是个勇敢的人。我会看看我是否可以更适应 rebase。
  • @JevonKendon 我在变基之前备份了文件夹。尽管如此,我只会强制推送以确保它没问题,所以如果我搞砸了,我可以从远程恢复。
猜你喜欢
  • 1970-01-01
  • 2013-09-29
  • 2016-01-24
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
相关资源
最近更新 更多