Git rebase子树

时间:2013-01-24 14:47:09

标签: git branch rebase

假设我有以下情况:

    o (master)   
   /       o--o (WIP1)
  /       /
 o--o--o--o--o--o (WIP2)
(X)       \
           o--o (WIP3)

是否有一个git命令创建一个新的分支,以便它包含分支X后的子树?我想要执行“大规模的反思”,我希望三个WIP分支在主人身上重新定位。

我知道我可以用一些Bash脚本来做到这一点,但我想知道如何使用git命令。

4 个答案:

答案 0 :(得分:12)

没有单一的git命令。你将不得不做一些手工工作。在你的情况下:

    o (master)   
   /        o--o (WIP1)
  /        /
 X--o--o--B--o--o (WIP2)
           \
            o--o (WIP3)

您首先将WIP1转换为主人:

git rebase --onto master X WIP1

将导致这一点:

               o--o (WIP1)
 (master)     /
    o--o--o--B’
   /   
  /        
 X--o--o--B--o--o (WIP2)
           \
            o--o (WIP3)

如果你现在运行git rebase --onto master X WIP2,你会得到这样的结构:

                o--o (WIP1)
 (master)      /
     o--o--o--B’
    / \
   /   o--o--B’’--o--o (WIP2)
  /        
 X--o--o--B--o--o (WIP3)

这可能不是您想要的,所以现在您应该在B’上重新定义WIP2和WIP3:

git rebase --onto B’ B WIP2 
git rebase --onto B’ B WIP3 

将导致这一点:

                  o--o (WIP1)
(master)         /
    o--X--o--o--B’--o--o (WIP2)
                 \
                  o--o (WIP3)

答案 1 :(得分:2)

   o (master)   
   /       o--o (WIP1)
  /       /
 o--p--p--o--o--o (WIP2)
(X)      (Y)
          \
           o--o (WIP3)

这应该是rebase --onto(您可以在“How to move certain commits to another branch in git?”中看到一个示例):

 git rebase --onto master X WIP1
 git rebase --onto master X WIP2
 git rebase --onto master X WIP3

来自Chronialtest,即可:

         p'--p'--o--o (WIP2)
        /
 o-----o-----p--p--o--o--o (WIP1)
(X) (master)   (Y')   
        \
         p''--p''--o--o (WIP3)

所以第一个rebase没问题,但你需要得到Y SHA,并且:

 git rebase --onto Y' Y WIP2
 git rebase --onto Y' Y WIP3

答案 2 :(得分:1)

我已将此问题标记为重复。我会写下我解释的内容 the other answer但请使用您的示例。

我用于此类用例的方法是合并所有分支 要移入1 常用的人工节点,然后使用rebase命令 使用--preserve-merges选项。合并所有分支将公开1 终点,将用作rebase --onto的最终输入参数。该 起点通常很明显,是子树移动的起源。

合并以获取子树端点时,冲突应该是明确的 避免。因此,应指示合并命令来解决它们 自动使用-Xours选项。合并结果并不重要 因为这些人工合并节点将在rebase之后被丢弃。

建议创建一个新的分支 pack ,以免丢失 原始参考。在上面的示例中,将使用以下命令 进行:

$ git checkout -b pack WIP1 # create new branch at 'WIP1'
$ git merge -s recursive -Xours WIP2 # merges WIP2 into pack (node p2)
$ git merge -s recursive -Xours WIP3 # merges WIP3 into pack

下面可以看到树会变成什么样。两个新的人工节点 已使用合并创建 p2 pack

      o (master)
     /
    /          (WIP1)  (p2)
   /        o-----o-----o----o (pack)
  /        /           /    /
 o--o--o--o-----o-----o    / (WIP2)
(X)        \              /
            o------------o (WIP3)

现在是时候改变了。从现在开始,所有人都有一个共同的终点 分支( pack ),可以很容易地移动整个子树:

$ git rebase --preserve-merges --onto master X pack

产生这个:

                      (WIP1') (p2')
                   o-----o-----o----o (pack')
   (master)       /           /    /
 o----o----o--o--o-----o-----o    / (WIP2')
(X)               \              /
                   o------------o (WIP3')

现在是时候重新安排参考文献了。在某些方面我不知道为什么 移动引用的情况,而其他引用则不移动。输入这个 每个参考WIP1,WIP2,WIP3或您需要的任何东西:

$ git checkout WIP1
$ git reset --hard <WIP1' hash>

最后,摆脱为其创建的人工提交 生成一个公共子树端节点。

$ git branch -D pack
$ git branch -D p2 # if there is any

所以最后一棵树将是:

                      (WIP1')
                   o-----o
   (master)       /
 o----o----o--o--o-----o-----o (WIP2')
(X)               \
                   o------------o (WIP3')

答案 3 :(得分:0)

如果您想获得此结果

    o (oldmaster)--o--o--B--o--o(WIP1)--o--o(WIP2)--o--o(WIP3)(master)  
   /        
  /        
 X

你应该这样做:

git rebase --onto master X WIP1         /* move WIP1 on master */
git rebase --onto WIP1 WIP2~3 WIP2      /* move WIP2 on WIP1 */
git rebase --onto WIP2 WIP3~3 WIP3      /* move WIP3 on WIP2 */
git reset --hard WIP3                   /* move master index to WIP3 */