Git:切换合并中的分支

ldxq2e6h  于 2023-02-28  发布在  Git
关注(0)|答案(3)|浏览(173)

我刚刚花了几个小时来解决将big-feature-branch-B合并到big-feature-branch-A时产生的合并冲突。我终于完成了,我的所有解决方案都已准备就绪,可以提交了。但是,我的工作流程是:
1.从big-feature-branch-A创建一个分支(我将此分支命名为AB-merge-branch
1.将big-feature-branch-B合并为AB-merge-branch
1.为创建PR以将AB-merge-branch合并到big-feature-branch-A中,以便解决方案可以通过代码评审。
在我解决合并冲突的大部分过程中,我意识到我是在big-feature-branch-A而不是合并分支中解决它们的。
我的问题是,如何在提交更改之前安全地更改分支?
我确信答案很简单,通常我只会隐藏我的修改,切换分支,然后弹出我的修改。然而,我从来没有在合并过程中这样做过,在这种情况下,我对“尝试一下”感到非常不安,因为我不想冒险再次解决所有这些冲突。我对我的git-fu也不是很有信心,我也读过像this这样的恐怖故事(但也许我的情况不同,因为我已经解决了所有冲突,所有更改都是分阶段进行的?),也不想在这个案子上做实验谢谢!

qyyhg6bp

qyyhg6bp1#

简短的回答是,你不能(切换分支...嗯,算是吧,虽然你可以,算是吧,但这并不明智--这涉及到直接篡改Git的内部):

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

您的索引处于这种特殊的“合并”状态,因此您也不能隐藏它。幸运的是,没有必要这样做。(如果您解决了所有问题,然后运行git checkout -b newbr并提交,您将得到一个非合并提交。您可以使用这个方法,但不要那样做。)
您应该做的是继续并完成合并:这会给你想要的merge result。然后你可以在想要的 * 分支 * 中重新开始merge,并获取你刚刚提交的结果作为想要的 result,* 如果有必要的话 *。然后你完全放弃原来的merge提交(如果有必要的话)。(如果你不小心用一个成功的git checkout -b破坏了merge,这也是你需要做的。
在某些情况下,包括你的情况,原始合并的父链接就是你想要的,这只是一个重新标记合并的问题。
我会先展示食谱,然后解释 * 为什么 * 它有效:

... 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

为什么这是一个答案(有多种方法,因此我不会说出 the 答案)

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

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

也就是说,正如git status所说的,“在分支big-feature-branch-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,但由于冲突而失败。您解决了(大部分)冲突(必须在继续之前解决所有冲突)。当您最终提交时,您将获得一个新的合并提交,这将移动 current 分支(HEAD记住的分支):

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

这里没有显示(因为太难显示)的是新合并M的 * 第一个 * 父节点是最右边(最近)的上一行提交,而第二个是下一行提交(如果有的话,当有人想要跟随“主”分支与“被合并的边功能”时,第一个与第二个东西稍后才重要:根据定义,主分支总是第一父分支)。
您忘记创建一个新分支 name,因此现在发生的情况如下:

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,你现在必须 backbig-feature-branch-A,用git reset来修复它(你可以使用其他命令,但是我坚持使用reset).如果你用git branch来创建新的分支,你的 current 分支是不受影响的:你还在big-feature-branch-A上。
在任何情况下,您都希望这个big-feature-branch-A分支名称后退一步,回到M的第一个父分支,就好像它从一开始就没有前进到M一样。(或停留在)这个分支上。一旦你在这个分支上,你可以使用git reset --hard HEAD^来实现这种后退一步。HEAD^意味着“找到HEAD的第一个父节点“,如果HEAD名称提交M(it does)-表示最右上方的行提交,这是您希望分支指向的位置。git reset命令执行分支的重定向,并且重置你的索引和工作树(以便在新的提交中一切都是干净的)。

dm7nw8vv

dm7nw8vv2#

首先,完成合并并提交,这样就不会丢失任何东西。
这是本地行动不会被其他人看到的。
从这个提交中,你可以创建分支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
p8h8hvxi

p8h8hvxi3#

稍微更正/补充一下@torek的回答,我发现如果我切换分支,在一个新分支上用git checkout -b AB-merge-branch提交冲突解决的合并,分支更改成功,但是作为分支更改的副作用,我也会丢失合并状态
当我提交时,我没有收到合并驱动提交消息建议,并且最终提交只有一个父提交。
为了从这个“意外创建了一个新的独立提交”状态到达我想要的位置,当然不需要重新解决我已经解决的冲突,假设我在AB-merge-branch上创建了这个“非合并提交”,我发现我需要做如下的事情:

git switch -c AB-merge-branch-corrected AB-merge-branch~1
git merge -s ours --no-commit big-feature-branch-B
git restore --worktree --staged --source AB-merge-branch -- .
git commit # I get the expected merge message prompt
git switch AB-merge-branch
git reset AB-merge-branch-corrected
git branch -d AB-merge-branch-corrected

一般来说,最简单的建议是 * 在开始合并之前创建新分支 *,完全按照工作流程的规定。
如果你 * 还没有切换分支 *,那么@torek上面的建议是正确的/最简单的。

相关问题