首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Git rebase子树

Git rebase子树
EN

Stack Overflow用户
提问于 2013-01-24 22:47:09
回答 4查看 3K关注 0票数 11

假设我有以下场景:

代码语言:javascript
复制
    o (master)   
   /       o--o (WIP1)
  /       /
 o--o--o--o--o--o (WIP2)
(X)       \
           o--o (WIP3)

有没有一个git命令可以创建一个新的分支,使其包含分支X之后的子树?我想执行一个“大型rebase",我想要基于master的三个WIP分支。

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

EN

回答 4

Stack Overflow用户

发布于 2013-01-25 00:14:17

没有单一的git命令可以做到这一点。你将不得不做一些体力劳动。在你的情况下:

代码语言:javascript
复制
    o (master)   
   /        o--o (WIP1)
  /        /
 X--o--o--B--o--o (WIP2)
           \
            o--o (WIP3)

首先将WIP1重新设置为master:

代码语言:javascript
复制
git rebase --onto master X WIP1

这将导致以下结果:

代码语言:javascript
复制
               o--o (WIP1)
 (master)     /
    o--o--o--B’
   /   
  /        
 X--o--o--B--o--o (WIP2)
           \
            o--o (WIP3)

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

代码语言:javascript
复制
                o--o (WIP1)
 (master)      /
     o--o--o--B’
    / \
   /   o--o--B’’--o--o (WIP2)
  /        
 X--o--o--B--o--o (WIP3)

这可能不是您想要的,所以现在您应该在B’上重新设置WIP2和WIP3的基础

代码语言:javascript
复制
git rebase --onto B’ B WIP2 
git rebase --onto B’ B WIP3 

这将导致以下结果:

代码语言:javascript
复制
                  o--o (WIP1)
(master)         /
    o--X--o--o--B’--o--o (WIP2)
                 \
                  o--o (WIP3)
票数 15
EN

Stack Overflow用户

发布于 2017-08-24 20:13:51

我已将此问题标记为重复。我将使用您的示例编写我解释过的the other answer

对于这种用例,我使用的方法是将所有要移动的分支合并到一个公共的人工节点中,然后使用带有--preserve-merges选项的rebase命令。合并所有分支将公开一个端点,该端点将用作rebase --onto的最终输入参数。起始点通常是显而易见的,子树的原点要移动。

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

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

代码语言:javascript
复制
$ 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。

代码语言:javascript
复制
      o (master)
     /
    /          (WIP1)  (p2)
   /        o-----o-----o----o (pack)
  /        /           /    /
 o--o--o--o-----o-----o    / (WIP2)
(X)        \              /
            o------------o (WIP3)

现在是时候重新建立基础了。由于现在所有分支(pack)都有一个公共端点,因此很容易使用以下命令移动整个子树:

代码语言:javascript
复制
$ git rebase --preserve-merges --onto master X pack

这会产生这样的结果:

代码语言:javascript
复制
                      (WIP1') (p2')
                   o-----o-----o----o (pack')
   (master)       /           /    /
 o----o----o--o--o-----o-----o    / (WIP2')
(X)               \              /
                   o------------o (WIP3')

现在是重新排列引用的时候了。我不知道为什么,在某些情况下,引用会移动,而在另一些情况下则不会。为每个引用WIP1、WIP2、WIP3或您需要的任何内容键入以下内容:

代码语言:javascript
复制
$ git checkout WIP1
$ git reset --hard <WIP1' hash>

最后,去掉为生成公共子树端节点而创建的人工提交。

代码语言:javascript
复制
$ git branch -D pack
$ git branch -D p2 # if there is any

所以最后的树应该是:

代码语言:javascript
复制
                      (WIP1')
                   o-----o
   (master)       /
 o----o----o--o--o-----o-----o (WIP2')
(X)               \
                   o------------o (WIP3')
票数 4
EN

Stack Overflow用户

发布于 2013-01-24 23:29:57

代码语言:javascript
复制
   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?”中看到一个示例):

代码语言:javascript
复制
 git rebase --onto master X WIP1
 git rebase --onto master X WIP2
 git rebase --onto master X WIP3

Chronialtest来看,这将给出:

代码语言:javascript
复制
         p'--p'--o--o (WIP2)
        /
 o-----o-----p--p--o--o--o (WIP1)
(X) (master)   (Y')   
        \
         p''--p''--o--o (WIP3)

因此,第一个rebase是可以的,但您需要获得Y SHA,并且:

代码语言:javascript
复制
 git rebase --onto Y' Y WIP2
 git rebase --onto Y' Y WIP3
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14504029

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档