2013-05-27 86 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