2014-01-18 60 views
2

假设我有一个这样的仓库:如何在合并提交中移动提交?

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

其中M是一个合并提交合并topicmaster

后来我发现C的错误,所以我做出承诺的master分支修复它,就M顶部:

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

回答

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做一次全部,但至少我知道这工作。

+0

由'git rebase -p'创建的合并提交是否已正确创建?如其中,其父母是否正确“C1”和“A”?在重新绑定合并时,我遇到了问题,因为合并更改以正常提交而不是合并提交重播。 – LopSae

+0

@LopSae:是的,合并提交是在C1'和A之上进行的。保留合并是'-p'(又名'--preserve-merges')的一点,但是有一个关于使用'-p'和'-i'一起在'git-rebase(1)'中提到。 – musiphil

1

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

首先提交你的修正,然后用git rebase -i移动M.

新前提交

为了避免再次化解矛盾,确保你有rerere.enabled集获得的git记住决议。您必须先解决它,然后才能记住它。 Rerere(重新使用记录的分辨率)是一个奇妙的功能。

+0

谢谢。你能更详细地解释'git rebase -i'命令吗?我尝试了'git rebase -i C',并且合并丢失了;我尝试过'git rebase -i -p C',并且'C1'提交会丢失,尽管我在交互模式下选择了“提交”提交。 – musiphil

1

这可以通过单个rebase来移动提交(或任意数量的提交),然后从主题重做合并。

# 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,你可以在合并之前移动更多的一次提交。你可以在阅读计划中的重订指令英文为:

抓住从提交到mergeCommitmaster衍合他们的beforeMerge顶部。

+0

是的,我看到这些分支的确是为了可读性。你可以用两个命令来完成相同的操作:'git rebase - 去掉master ^^ master^master'后跟'git merge topic'。 (不必删除临时分支是额外的好处。) – musiphil