3

假设我有一个这样的存储库:

I --- C --- M    master
  \       /
   `- A -´       topic

M合并topicmaster. _

后来我在 中发现了一个错误,所以我在分支上C提交了一个修复它的问题,位于:masterM

I --- C --- M --- C1    master
  \       /
   `- A -´              topic

但理想情况下,我希望历史看起来像这样:

I --- C --- C1 --- M    master
  \              /
   `- A --------´       topic

如何重写历史记录,以便C1在合并之前出现M

我可以删除M,应用由 制作的补丁C1,然后再次合并topicmaster再次解决所有冲突,但我想避免这种努力,我更愿意保留原始提交信息(作者、日期等)如果可能的话,这排除了git commit再次做的可能性。我希望它是可能的git rebase,但我失败了,其中一个或两个-p-i

4

3 回答 3

2

这可以通过一个变基来移动提交(或任意数量的提交)然后从主题重做合并来完成。

# Create some branches just for readability
git branch mergeCommit master^
git branch beforeMerge master^^

# Run the rebase
git rebase --onto beforeMerge mergeCommit master
# After the rebase master will have the replayed commits on top of C

# Redo the merge
git merge topic

有了这个 rebase,你可以在合并之前移动多个提交。您可以将计划英语中的变基指令阅读为:

mergeCommitto获取提交master并将它们重新设置在beforeMerge.

于 2014-01-22T01:33:35.613 回答
1

第三张图中的提交 M 与第二张图中的 M 不同,因为它具有不同的祖先。因此,您必须在 M 之前将 master 重置回来,或者使用 rebase 来完成。

首先提交您的修复,然后使用git rebase -i将新提交移到 M 之前。

为避免再次解决冲突,请确保您已rerere.enabled设置让 git 记住解决方案。不过,您必须在第一次解决它之前执行此操作,以便记住它。Rerere(重用记录的分辨率)是一个很棒的功能。

于 2014-01-18T06:17:02.487 回答
1

我发现的最好方法是:

git checkout -b tmp master^^
# Now tmp is on top of C

git cherry-pick master
# Now tmp is on top of C1', a copy of C1

git rebase -p tmp master
# Now master is on top of a merge commit from C1' and A

git branch -d tmp

我不知道为什么git rebase不能在没有 的情况下一次完成这一切git cherry-pick,但至少我知道这是可行的。

于 2014-01-18T18:17:27.093 回答