Git:在合并中切换分支

时间:2017-07-27 02:52:17

标签: git git-merge

我花了最后几个小时来解决因将big-feature-branch-B合并到big-feature-branch-A而导致的合并冲突。我终于完成了,我的所有决议都已上演并准备好承诺。但是,我工作的过程是:

  1. big-feature-branch-A创建分支(我将此分支称为AB-merge-branch
  2. big-feature-branch-B合并到AB-merge-branch
  3. 创建一个PR以将AB-merge-branch合并到big-feature-branch-A中,以便解决方案可以通过代码审核。
  4. 当我通过解决合并冲突的大部分时间时,我意识到我在big-feature-branch-A而不是合并分支中解析它们。

    我的问题是,如何在提交更改之前安全地更改分支?

    我确信答案很简单,通常我会隐藏我的更改,切换分支,然后弹出我的更改。但是,我从来没有在合并过程中做到这一点,在这种情况下,我对于“尝试它”非常怯懦,因为我不想冒险再次解决所有这些冲突,而且我不是超级对我的git-fu充满信心。我也读过像this这样的恐怖故事(但也许我的情况有所不同,因为我已经解决了所有的冲突,所有的变化都是上演的?),并且不想在这种情况下进行实验。谢谢!

2 个答案:

答案 0 :(得分:2)

简短的回答是你不能(切换分支......好吧,有点,尽管你可以,但是它不可取 - 它涉及直接用Git的内脏进行修改):

$ git checkout -b newbr
foo.txt: needs merge
error: you need to resolve your current index first

您的索引处于此特殊“合并”状态,因此您也无法存储。幸运的是,没有必要这样做。 (如果你解决了所有问题,然后运行git checkout -b newbr并提交,你会得到一个非合并提交。你可以使用它,但是不要这样做。)

您应该做的是继续并完成合并:这将为您提供所需的合并结果。然后,您可以在所需的分支中重新启动合并,并将您刚刚提交的结果作为结果获取,如果有必要的话 EM>。然后,您完全放弃原始合并提交(如有必要)。 (如果您不小心使用上面几乎显示的成功git checkout -b破坏了合并,这也是您需要做的事情。)

在某些情况下 - 包括你的案例 - 原始合并的父链接是你想要的,并且只需要重新标记合并。

我将首先展示食谱,然后解释为什么它起作用:

... finish merging ...
$ git commit                         # commit the merge
$ git checkout -b AB-merge-branch    # create the merge branch
$ git checkout big-feature-branch-A  # get back to other branch
$ git reset --hard HEAD^             # take the merge off of it

为什么这是一个答案(有多种方式,所以我不会说 答案)

让我们绘制您第一次开始合并时的设置:

       o--...--o--o   <-- big-feature-branch-A (HEAD)
      /
...--*
      \
       o--...--o--o   <-- big-feature-branch-B

也就是说,正如git status所说的那样,“你在分支大特征分支A上”并且一切都很顺利。每个o代表一个提交(我标记了合并基础,对于合并,用星号)。

然后打算运行git checkout -b AB-merge-branch。如果已经完成了,那么图片将如下所示:

    o--...--o--o   <-- big-feature-branch-A, AB-merge-branch (HEAD)
   /
--*
   \
    o--...--o--o   <-- big-feature-branch-B

您运行git merge,但因冲突而失败。您解决了(大部分)冲突(必须在继续之前解决所有冲突)。当你最终提交时,你将获得一个新的合并提交,这将移动当前分支(由HEAD记住的分支):

    o--...--o--o   <-- big-feature-branch-A
   /            \
--*              M   <-- AB-merge-branch (HEAD)
   \            /
    o--...--o--o   <-- big-feature-branch-B

这里没有显示(因为它太难显示)是新合并M第一个父是最右边(最新)的上行提交,第二个是较低的。 (如果有人想要跟随“主要”分支和“合并的侧面特征”,那么第一个与第二个东西之后会有关系:根据定义,主分支始终是第一个父分支。)

你忘了创建一个新的分支名称,所以现在发生的事情是这样的:

    o--...--o--o
   /            \
--*              M   <-- big-feature-branch-A (HEAD)
   \            /
    o--...--o--o   <-- big-feature-branch-B

第一个父级仍然是最顶层和最右侧的提交,第二个父级仍然是最底层的提交。新合并提交M完全相同。只是移动指向新合并M标签big-feature-branch-A(HEAD的那个),而不是不存在的AB-merge-branch(这显然不是HEAD)。

所以你现在要做的就是创建你想要的标签。使新分支名称AB-merge-branch指向M的任何内容都足以满足该部分。您可以使用git checkout -b AB-merge-branchgit branch AB-merge-branch来执行此操作。

如果您确实使用git checkout -b,则现在必须返回<{1}}以使用big-feature-branch-A进行修复(您可以使用其他命令,但我坚持git reset这里。如果您使用reset创建新分支,则当前分支不受干扰:您仍然在git branch

在任何情况下,您都希望此big-feature-branch-A分支名称向后移动一步,转移到big-feature-branch-A的第一个父级,就像它在第一个中从未向前移动到M一样地点。所以你重新开始(或继续)这个分支。一旦你进入这个分支,你可以使用M来实现这个后退一步。 git reset --hard HEAD^表示“找到HEAD^的第一个父级”,如果HEAD名称提交HEAD(它确实) - 意味着最右边的上一行提交,这就是你的位置希望分支指向。 M命令重新指向分支,并重新设置索引和工作树(以便新提交中的所有内容都干净利落)。

答案 1 :(得分:1)

首先,完成合并并提交。这样,你就不会失去任何东西 这是一项本地行动,不会被其他任何人看到。

从该提交中,您可以创建分支AB-merge-branch

 git checkout -b AB-merge-branch

您可以将之前的big-feature-branch-A重置为其第一个父提交。

 git branch --force big-feature-branch-A big-feature-branch-A^1