2014-01-18 59 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