如何从一个重新分支的分支机构中重新分支?

时间:2015-08-07 15:50:39

标签: git branch rebase git-rebase

所以我的历史看起来像这样:

o---o---o---o master \ o---o---o A \ o B

所以,解释一下:

  • 我的分支A是从master
  • 开始的
  • 我有从B
  • 开始的分支A(只有1次提交)

我想要的是:

o---o---o---o master \ o---o---o A \ o B

我做的是:

1)。

git checkout A git rebase master

这导致了很多冲突,经过一段时间的修复后,出现了以下历史:

o---o---o---o master \ o---o---o A

这正是我想要的。

(我不知道B现在在哪里)

2)。

在此之后我做了很多南瓜并改变了A的提交顺序,使历史看起来像我想要的。

3)。

现在,我还想做的是:

git checkout B git rebase A

然而,这似乎不起作用,我不知道为什么。如果我git log,我会在执行第1步之前看到那些提交。

另外,我得到了我在第1步已经解决过的大量冲突。我花了很多时间做这件事,不想再这样做了。

This example建议使用--onto,我这样做了:

git checkout B git rebase --onto A

但是这会完全删除B上的提交,并使AB指向同一个提交,即A上的最后一个提交。

我的问题是:如何才能有效地将B关闭A以使其看起来像B从A 开始? (这在开始时确实如此)。

我最好的猜测是我使用--onto错了。或者我应该使用别的东西(比如cherry-pick)。

3 个答案:

答案 0 :(得分:31)

的简短回答如何才能有效地将B关闭A以使其看起来像B从A开始? 假设您想要移动一个提交:

git rebase --onto A B~ B

如果你想移动多一个提交使用:

git rebase --onto A old_A B

答案的其余部分。

您的B分支仍然存在(您可以查看),但其父级仍然是A之前的确切提交对象。
看到我使用的图形表示:

git log --graph --decorate --all

查看所有分支机构以及它们相互之间的位置。

你原来拥有的东西:

o---o---o---o  master
     \
      o---o---o  A
               \
                o B

你现在拥有什么:

o---o---o-----------o  master
     \               \
      o---o---o(B~)   o---o---o A
               \
                o B

在使用--onto方面,您需要有一个起点和一个终点。 使用方法:

git rebase --onto [target] [rebasing stops] [rebasing head]
git rebase --onto A B~ B

你得到了什么:

o---o---o----------o  master
     \              \
      o---o---o      o---o---o A
            (old_A)           \
                               o B

[branch_name]~表示分支的父提交。

B~是您不想更改的分支。 (它恰好是旧的A

或者,如果B是唯一一个将A作为父级的提交,(即,B是从master分支的提交链的末尾),则可以执行

git checkout B
git rebase master
git checkout B~   # this is the commit before B (the A commit)
git branch -d A   # remove the old A branch (it was rebased, and so is now invalid
git branch A      # recreate the A branch on the commit that is based on the original A

答案 1 :(得分:5)

我在git flow中遇到了同样的问题,并且我找到了一种最快,最好的方法。

(1)开始时的项目历史记录:

    master ---A---B---C
                \
                 D---E---F feature1
                          \
                           G---H feature2

(2)将feature1重新设置为主节点并强制按下:

    master ---A---B------------------------C
                \                           \
                 D---E---F feature1(old)     D---E---F feature1
                          \
                           G---H feature2

(3)将feature2改编为featrue1(新的)

    master ---A---B---C
                       \
                        D---E---F feature1
                                 \
                                  G---H feature2

最困惑的部分是如何做(3) ..但没有人对此有明确的答案。

我相信很多人都遇到了与我相同的问题,当我们尝试进行“重新设置基础”时,我们发现 feature1(old)实际上不存在!

    git rebase --onto feature1 feature1(old) feature2

解决方案是改用下面的方法:

    git rebase --onto feature1 feature1@{1} feature2
  

语法feature1 @ {1}表示“ rebase之前Feature1的最后一个已知状态”,答案可参考https://coderwall.com/p/xzsr9g/rebasing-dependent-branches-with-git

答案 2 :(得分:1)

如果你已经重新开始A.应该是B就在你离开的地方。 A的分支(指针)只是移动到它的新位置。

如果你建议的话,我建议有效地将B变为A的是使用'cherry-pick'。此命令尝试将提交中所做的更改应用于运行它的分支。

因此,如果B最初指向的提交的提交ID为“123456”,那么我建议将当前的“B”移动到与git branch -f B A的新“A”相同的位置,然后运行{{ 1}}将更改应用到A。

我相信git cherry-pick 123456标志用于设置应用提交的目标位置。默认为“上游”(来源:http://git-scm.com/docs/git-rebase)。

我喜欢考虑rebase命令的方式如下:

--onto

使用它,将B重新绑定到master上然后将A指向B之前的提交可能更简单。

git rebase --onto <Starting here> <Apply all commits from HERE> <TO HERE>

(因为起点( - 多)隐含'主')

然后使用git rebase master B (^表示'父母')