将特性分支变基到另一个特性分支上

436

我有两个(私有的)功能分支正在进行中。

a -- b -- c                  <-- Master
     \     \
      \     d -- e           <-- Branch1
       \
        f -- g               <-- Branch2

在我处理这些分支一段时间后,我发现需要将Branch2的更改合并到Branch1中。我想要将Branch2的更改变基于Branch1。最终我希望得到以下结果:

a -- b -- c                  <-- Master
           \
            d -- e -- f -- g <-- Branch1

我相信我需要将第二个分支合并到第一个分支上,但我不确定正确的语法以及我应该检出哪个分支。

这个命令会产生预期的结果吗?

(Branch1)$ git rebase --onto Branch1 Branch2

17
回答你的问题,我会创建一个测试仓库,按照你展示的提交结构进行操作,然后尝试你提供的命令。但我认为你自己也可以做到这一点,所以我不会去做 :) - Daniel Hilgarth
6
谢谢。我太过于专注于第一次就做好这件事,以至于没有想到我可以轻松地自己测试它 :-) - Arjen
6
我明白了,这就是我发表那条评论的原因 :) 每当我做一些事情时,我不确定它是否会按照我的预期执行,我都会创建一个测试仓库并在那里进行测试。或者,我会复制我的真实仓库,并在复制品上进行测试。 - Daniel Hilgarth
2
注意:Git 2.0将引入这种rebase的快捷方式:git rebase -。请参见我的下面的答案 - VonC
8
小注:这里的答案给出了分支2作为结果。原帖子想要分支1。或者我漏看了什么? - Josef.B
显示剩余2条评论
5个回答

488
  1. 切换到Branch2分支

git checkout Branch2
  • 将当前(Branch2)的更改应用于Branch1的更改之上,保持在Branch2中:

  • git rebase Branch1
    

    这将使您在Branch2中获得所需的结果:

    a -- b -- c                      <-- Master
               \
                d -- e               <-- Branch1
               \
                d -- e -- f' -- g'   <-- Branch2
    

    你可以删除 Branch1。


    32
    他不是想要所有的更改都在Branch1吗? - tomasz_kusmierczyk
    13
    这似乎和他想要的相反,不是吗? - 1252748
    4
    确实,@tomasz_kusmierczyk和@1252748,我自己也感到困惑。但后来我意识到,在保持在Branch1的情况下执行git rebase会重写Branch1的历史记录,将Branch1的更改放在从Branch2复制的更改之上。这将导致以下提交顺序:a - b - f - g - c' - d' - e' - eel ghEEz
    9
    @tomasz_kusmierczyk和1252748,这并不是他想要的相反情况,而是他确切想要的。分支名称并不重要,您可以随时更改它们。 - a3y3
    1
    @a3y3 分支名称确实很重要。如果您想变基一个有未合并拉取请求的分支,您不能使用这种方法,对吧? - Nadav
    显示剩余3条评论

    71
    注意:如果你之前在Branch1分支上,那么在Git 2.0(2014年第二季度)中,你将可以输入以下命令:
    git checkout Branch2
    git rebase -
    
    在这种情况下,-作为rebase参数的意思是“我们之前所在的分支”。请参见Brian Gesiak modocache的提交记录commit 4f40740

    rebase: 允许使用“-”代替之前的分支名称

    教会rebasecheckoutmerge相同的简写方式来命名将当前分支rebase到的分支。也就是说,“-”表示“我们之前所在的分支”。

    请谨慎使用此功能,因为它不够明确,小错误可能会导致混乱的状态。


    61
    不错,但有些危险。有时冗长的表述胜出。但话说回来,我也喜欢Java... (-: - sthzg

    23
    这个解决方案应该完全满足要求(在Branch1的基础上添加Branch2的提交记录而仍然保留在Branch1上)。
    git checkout Branch1
    git cherry-pick master..Branch2
    

    你最终会得到这个。

    a -- b -- c                      <-- Master
               \
                d -- e -- f' -- g'   <-- Branch1 (current)
               \
                f -- g               <-- Branch2
    

    这将按顺序从Branch2上挑选每个提交并应用到Branch1上。然后您可以删除Branch2。


    这非常有用。我在另一个(本地)分支的顶部进行了一些提交,但尚未推送到git。我使用了 git cherry-pick mybranch...origin/mybranch 将这些提交挑选到当前分支。 - Smar
    如果您正在将一个特性分支合并到另一个特性分支中,这种方法是行不通的。对于这种情况,请使用以下命令:git cherry-pick <current-branch>..<other-branch> - Chris Perry

    11

    我知道你要求使用变基,但我会选择将我想要从Branch2移动到Branch1的提交挑选出来。这样,我就不需要关心哪个分支是从主分支创建的了,而且我可以更好地控制合并。

    a -- b -- c                  <-- Master
         \     \
          \     d -- e -- f -- g <-- Branch1 (Cherry-Pick f & g)
           \
            f -- g               <-- Branch2
    

    6
    我是否误解了这个问题?我的直觉是使用rebase--onto标志,如下所示:
    git rebase --onto branch1 master branch2
    

    在变基之前:

    * 6263580 (HEAD -> branch2) add g
    * c802c88 add f
    | * c80cfb0 (branch1) add e
    | * aea5708 add d
    | * 2e522fe (master) add c
    |/  
    * 0613527 add b
    * e2a0c4d add a
    

    变基之后:

    * 7f6a363 (HEAD -> branch2) add g
    * 4cbab60 add f
    * c80cfb0 (branch1) add e
    * aea5708 add d
    * 2e522fe (master) add c
    * 0613527 add b
    * e2a0c4d add a
    

    这样做可以明确地表明哪一组提交将被重新设置到哪里,使得情况清晰明了。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接