11

假设我有以下场景:

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

是否有一个 git 命令创建一个新分支,以便它包含分支 X 之后的子树?我想执行“大型变基”,我希望三个 WIP 分支基于 master。

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

4

4 回答 4

15
于 2013-01-24T16:14:17.030 回答
4

我已将此问题标记为重复。我会写下我解释 的另一个答案,但使用你的例子。

我用于此类用例的方法是将所有要移动的分支合并到 1 个公共人工节点中,然后使用带有--preserve-merges选项的 rebase 命令。合并所有分支将公开 1 个端点,该端点将用作rebase --onto. 起点通常很明显,要移动的子树的原点。

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

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

$ 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

下面可以看到树会变成什么。通过合并创建了两个新的人工节点 p2pack 。

      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')
于 2017-08-24T12:13:50.500 回答
2
   o (master)   
   /       o--o (WIP1)
  /       /
 o--p--p--o--o--o (WIP2)
(X)      (Y)
          \
           o--o (WIP3)

这应该是一个(您可以在“如何将某些提交移动到 git 中的另一个分支?rebase --onto ”中看到一个示例):

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

Chronial测试中,这将给出:

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

所以第一次变基是可以的,但是你需要得到 Y SHA,并且:

 git rebase --onto Y' Y WIP2
 git rebase --onto Y' Y WIP3
于 2013-01-24T15:29:57.017 回答
1

使用git-branchless这套工具,您可以直接变基子树:

$ git move -b WIP1 -d master

免责声明:我是作者。


如果您想坚持使用基本 Git,您可以使用此答案中的方法,但使用新--rebase-merges选项。做一个虚拟的合并提交:

$ git checkout WIP1
$ git merge WIP2 WIP3
...add all conflicts and resolve...

然后以交互方式执行变基。生成的变基计划将是您想要的,除了您应该删除最后一个merge命令:

$ git rebase -i master --rebase-merges
...example editor contents below...
label onto

# Branch WIP1
reset abc123 
pick abc456
pick abc789
label abcdef

reset onto
pick bcd123
pick bcd456
pick bcd789

## REMOVE THIS LINE:
# merge -C abcdef
于 2021-09-30T17:32:45.087 回答