2013-05-27 84 views
32

讓我描述我的情況:混帳:拉重建基礎分支

金髮先生和橙色先生是在分支一分支出的主分支上提交M1的工作。分支A有2個提交:A1和A2。

M1 
    \ 
    \ 
    A1 - A2 

與此同時,Orange先生承諾並在主分支M2和M3上再推出2次提交。

M1 - M2 - M3 
    \ 
    \ 
    A1 - A2 

金髮先生從遠程拉,和一段時間後決定重訂到主分支:

M1 - M2 - M3 
    \   \ 
    \   \ 
    A1 - A2 A1` - A2` 

現在A1`和A2`是在先生金髮的本地存在的衍合的提交, A1和A2遠程存在。 Blond先生推動他的提交,使用-f強制他的更改和「重寫」歷史記錄。現在遠程倉庫看起來像這樣:

M1 - M2 - M3 
      \ 
       \ 
       A1` - A2` 

但是Orange先生也在A分支上工作。他的本地存儲庫仍然如下所示:

M1 - M2 - M3 
    \ 
    \ 
    A1 - A2 

Orange爲了與遠程存儲庫中的分支同步需要做什麼?

正常拉不起作用。請問拉--f強制從本地遠程更改?我知道刪除A的本地版本並將它從遠程存儲庫中再次引入將會實現這一訣竅,但這似乎不是實現該目標的好方法。

回答

21

我的建議(或者,「如果我是橙先生,我會怎麼做」)是從git fetch開始的。現在,我將在我的回購庫中有這個,這是布隆德先生在重組之後以及在「git push -f」之前執行的。

M1 - M2 - M3 
    \   \ 
    \   \ 
    A1 - A2 A1' - A2' 

的一個重要區別是,我有我的本地標籤A指向修訂版A2,和遠程標籤remotes/origin/A指向A2' (金髮先生有它周圍指向其他的方式,局部標籤A指向A2的A2'和remotes/origin/A)。

如果我一直對我的命名分支副本「A」我要這個:

M1 ---- M2 ---- M3 
    \    \ 
    \    \ 
    A1 - A2 - A3 A1' - A2' 

(與本地標籤指向A3,而不是A2;或A4或A5等等,取決於我已經應用了多少變化。)現在我所要做的就是將我的A3(和A4,如果需要的話)重新貼到A2'上。一個明顯的直接的方式:

$ git branch -a 
    master 
* A 
    remotes/origin/master 
    remotes/origin/A 
$ git branch new_A remotes/origin/A 
$ git rebase -i new_A 

,然後刪除轉速A1和A2完全,因爲修改後的有在new_A爲A1' 和A2' 。或者:

$ git checkout -b new_A remotes/origin/A 
$ git format-patch -k --stdout A3..A | git am -3 -k 

(該git am -3 -k方法在git-format-patch手冊頁中描述)。

這些都需要搞清楚什麼我有一個金髮先生沒有他做了他rebase,即確定A1,A2,A3等

如果第二個方法是成功的我結束了之前:

M1 ---- M2 ---- M3 
    \    \ 
    \    \ 
    A1 - A2 - A3 A1' - A2' - A3' 

在我的分支名new_A點A3' (我現有A分支仍然指向舊A3)。如果我使用第一種方法並且成功了,那麼我最終會得到同樣的結果,就是我現有的分支名稱A現在將指向A3'(並且我沒有爲具有A1-A2-A3的舊分支命名,甚至儘管它仍然在我的回購庫中;找到它需要通過reflogs或類似的)。

(如果我的A3需要修改成爲A3' ,無論是互動底墊和‘混帳上午’方法將需要通過我的工作,當然。)

當然它也可能只是git merge(如由加里Fixler答案),但是這將創建一個合併提交(「M」,沒有數,下同),並保持轉速A1和A2可見,贈送:

M1 ---- M2 ---- M3 
    \    \ 
    \    \ 
    A1 - A2 - A3 A1' - A2' -- M 
       \_______________/ 

如果你想保留原來的A1和A2,這是一件好事;如果你想擺脫它們,這是一件壞事。所以「做什麼」取決於「你想要結果是什麼」。

編輯補充:我更喜歡format-patch方法,因爲它讓我的老A分支名稱保留下來,同時確保一切都很好。假設所有的工作和好,這裏是最後幾個步驟:

$ git branch -m A old_A 
$ git branch -m new_A A 

,然後,如果old_A可以完全放棄:

$ git branch -D old_A 

,或者等價地,開始與分支刪除,然後重命名new_A至A.

(編輯:又見git rebase --onto的文檔,爲基礎重建A3等,到new_A分支的目標。)

30

如果橙先生不介意失去了他的變化,他可以從服務器獲取,然後git checkout A2讓到他的地方A2分支,然後(假設遠程名爲「起源」)git reset --hard origin/A2重置他A2到遙控器的地址是A2

如果他擔心丟失更改,他可以合併服務器的更改以解決它們(從他自己的A2分支,並再次假定該遠程被命名爲「起源」),其中git merge origin/A2。這將在他和遠程的A2分支之上進行新的提交,並將兩者的更改合併在一起。然後這可以推回到遙控器。

+1

注意: '--'和'hard'之間沒有空格 - 我花了一段時間,因爲答案恰好在我的屏幕上被包裹在這兩個之間:) – qbolec