2013-04-01 45 views
21

我原本在'newfeature'分支工作,並且我被要求緊急修復活動分支上的一個錯誤。我創建了一個名爲'generalmaintenance'的分支,完成了這項工作,然後轉而開發併合並了它。現在我想返回'newfeature'分支併合並早期合併的更改。合併後爲什麼GIT會說「已經最新」,但分支之間的差異仍然存在?

當我切換到'newfeature'併合併到'develop'中時,3個文件中存在衝突。

我陷入糾結解決衝突,最終決定使用Aptana Studio 3(這是我的IDE)的「團隊」菜單中的「恢復」命令。我預計這會讓我回到合併之前,似乎已經完成了。

無論如何,當我在合併「發展」了,它說,Already-up-to-date,但兩個分支之間比較文件時,他們有很大的不同,我在另一個分支中添加的更改不會被合併英寸

請問我現在如何合併這兩個分支?

回答

46

還原梅傑斯與復位梅傑斯

我的猜測是,你實際上是Already-up-to-date

問題是git revert沒有撤消合併,它只解除了合併帶來的更改。當你創建一個合併提交時,你結合了這兩個分支的提交歷史。

合併

 develop 
     | 
A---B---C 
\  \ 
    E---F---M 
      | 
     newfeature 

在上述情況下,develop合併到newfeature,創建M提交。如果要運行git log newfeature,則會看到兩個分支的所有提交,但從newfeature分支的角度來看,所有這些更改都是由M提交執行的。

還原

git revert命令不會刪除任何承諾,而是創建一個新的提交該撤銷的變化是,提交包含。例如,如果你有一個提交含有這種差異...

-This is the old sentence. 
+This is ne new sentence. 

然後恢復這一點,revert命令將創建一個新的承諾,只是預製相反的差異,它只是翻轉跡象。

-This is ne new sentence. 
+This is the old sentence. 

這對於撤消其他開發者已經提交的提交造成的破壞非常有用。它向前移動歷史而不是改變歷史。

還原梅傑斯

然而,在非快進的情況下合併它可能有不期望的影響。

 develop 
     | 
A---B---C 
\  \ 
    E---F---M---W 
       | 
     newfeature 

假設W是一個逆轉提交,你可以看到如何運行git log newfeature仍然將包括所有從開發分支提交。因此,從develop的其他合併將無法正常工作,因爲它沒有看到您的分支丟失任何東西。

使用git reset,而不是復歸。

在未來,你可能要考慮使用git reset --hard <ref>(其中<ref>是合併的提交哈希值),如果合併尚未與其他開發者共享撤消合併。在上面的示例中,在創建合併提交M後,運行命令git reset --hard F將導致以下情況。

 develop 
     | 
A---B---C 
\  \ 
    E---F---M 
     | 
    newfeature 

正如你可以看到這個技術不泯犯一些人傾向於認爲,它只是移動你的分支回到提交您選擇。現在,如果您運行的是git log newfeature,則只會提交FEA。現在合併實際上已經從您的分支機構歷史中消失,因此稍後嘗試重新合併在develop將不會導致任何問題。

這種方法也不是沒有它的併發症。意識到你現在正在修改歷史記錄,所以如果在M合併後newfeature分支被推送到遠程分支,那麼git會認爲你已經過時了,並告訴你需要運行git pull。如果它只是你在那個遠程分支上工作,那麼請隨時撥打force-push - git push -f <remote> <branch>。這將產生與重置相同的效果,但在遠程分支上。

如果正在使用多個開發者,誰還會有現在已經從它拉到這個分支 - 那麼這是一個壞主意。這就是git revert很有用的原因,因爲它在不改變實際歷史的情況下撤消更改。

歷史上使用復位真的是隻在選項還沒有被共享的提交。

解決方案 - 恢復逆轉。

如果合併提交已被共享,那麼最好的方法可能是在該合併上使用git revert。但是,正如我們之前所說的那樣,您不能再簡單地將分支合併回來,並期望來自該分支的所有更改重新出現。答案是恢復恢復提交。

可以說你在develop分支做了一些工作後,在newfeature尊敬合併。你的歷史看起來像這樣。

  develop 
      | 
A---B---C---D 
\  \ 
    E---F---M---W 
       | 
     newfeature 

如果合併developnewfeature現在,你只會得到D因爲它的唯一的承諾,是不是已經newfeature分支的歷史的一部分。你還需要做的是恢復W提交 - git revert W應該做的伎倆之後git merge develop

    develop 
        | 
A---B---C-----------D 
\  \   \ 
    E---F---M---W---M---G 
         | 
       newfeature 

這將恢復提交由最初合併的所有更改 - 這實際上是由CB製成,但在W還原了,它再通過一個新的合併帶來了D提交G我建議恢復的復歸之前合併在develop最近的變化,我懷疑這樣做的順序會觸發衝突的可能性較低。

TL; DR

復歸創建一個 '恢復提交'。撤銷還原時,需要對第一次還原時創建的還原提交運行還原命令。應該很容易找到,git傾向於自動評論回覆,以便他們以「恢復」一詞開始。

git revert <commit>

+0

非常感謝埃迪,爲的是詳細的解釋(+1)。在接受你的答案之前,將再次研究它以消化它並嘗試你的解決方案。我'安靜地相信'這將是解決方案。 –

+1

僅供參考:我做了一些小的但重要的修改來糾正一些事情。最重要的是,我更正了我的示例以恢復合併提交。它是'git revert M',我將它改正爲'git revert W'。另外,第二個差異是錯誤的。一個解釋恢復提交。修正+/-符號。 – eddiemoya

+0

瞭解我們的教訓 - 小心git diff和審覈提交,如果合併來自同一個分支的產生恢復的PR! – f01

相關問題