Git:在合并中切换分支
Git: switch branches mid-merge
我刚刚花了最后几个小时来解决因将 big-feature-branch-B
合并到 big-feature-branch-A
而导致的合并冲突。我终于完成了,我所有的决议都已上演并准备好投入使用。但是,我工作的流程是:
- 创建
big-feature-branch-A
的分支(我将此分支称为 AB-merge-branch
)
- 将
big-feature-branch-B
合并到 AB-merge-branch
- 创建一个 PR 以将
AB-merge-branch
合并到 big-feature-branch-A
,以便决议可以通过代码审查。
当我解决合并冲突的大部分过程时,我意识到我是在 big-feature-branch-A
而不是合并分支中解决它们。
我的问题是,如何在提交更改之前安全地更改分支?
我相信答案很简单,通常我只是隐藏我的更改,切换分支,然后弹出我的更改。但是,我从来没有在合并过程中这样做过,在这种情况下,我对 "trying it" 感到非常不安,因为我不想冒险不得不再次解决所有这些冲突,而且我也不是对我的 git-fu 超级自信。我也读过类似 this 的恐怖故事(但也许我的情况不同,因为我已经解决了所有的冲突,并且所有的变化都是上演的?),并且不想在这种情况下进行试验。谢谢!
首先,简单地完成合并和提交。这样你就不会丢失任何东西。
这是本地操作,不会被其他人看到。
从该提交中,您可以创建分支 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
简短的回答是你不能 (switch b运行ches ... Git):
$ git checkout -b newbr
foo.txt: needs merge
error: you need to resolve your current index first
您的索引处于这种特殊的 "merging" 状态,因此您也无法存储。幸运的是,没有必要这样做。 (如果你解决所有问题,然后 运行 git checkout -b newbr
并提交,你会得到一个 non-merge 提交。你可以使用它,但我们不要那样做。)
您应该做的是继续并完成合并:这将为您提供所需的合并 结果。然后你可以 re-start 在你想要的 b运行ch 合并,并获取你刚刚提交的结果作为 result 你想要,如果有必要的话。然后您完全丢弃原始合并提交(如果需要)。 (如果您不小心破坏了成功的合并 git checkout -b
,这也是您需要做的,几乎如上所示。)
在某些情况下——包括你的情况——原始合并的parent链接就是你想要的,这只是重新[=79=的问题]标记合并。
我会先展示食谱,然后再解释为什么它有效:
... 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
所说的那样,您 "on branch 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 b运行ch(HEAD
记住的那个):
o--...--o--o <-- big-feature-branch-A
/ \
--* M <-- AB-merge-branch (HEAD)
\ /
o--...--o--o <-- big-feature-branch-B
这里没有显示(因为太难显示)是新合并的firstparentM
最右边(latest ) 上行提交,第二行是下行。 (第一和第二的东西以后很重要,如果有的话,当有人想关注 "main" b运行ch vs "side features that were merged in" 时:主要的 b运行ch 总是首先 parent,根据定义。)
您忘记创建一个新的 b运行ch name,所以现在发生的是:
o--...--o--o
/ \
--* M <-- big-feature-branch-A (HEAD)
\ /
o--...--o--o <-- big-feature-branch-B
第一个 parent 是 仍然是 top-and-right-most 提交,第二个 parent 仍然是底部这样的提交。新的合并提交 M
完全相同 。只是 label 移动,指向新的合并 M
,是 big-feature-branch-A
(那个是 HEAD),而不是不存在的 AB-merge-branch
(这显然不是 HEAD)。
所以您现在要做的就是创建您想要的标签。使新 b运行ch 名称 AB-merge-branch
指向 M
的任何内容都足以满足该部分的要求。您可以使用 git checkout -b AB-merge-branch
或 git branch AB-merge-branch
来做到这一点。
如果你确实使用 git checkout -b
,你现在必须 返回 到 big-feature-branch-A
以使用 git reset
修复它(还有其他您可以使用的命令,但我在这里坚持使用 reset
)。如果您使用 git branch
创建新的 b运行ch,您的 current b运行ch 不受干扰:您仍在 big-feature-branch-A
.
无论如何,您希望这个 big-feature-branch-A
b运行ch 名称后退一步,到 M
的第一个 parent,就好像它有一开始就没有前进到 M
。所以你回到(或继续)这个 b运行ch。一旦你在这个 b运行ch 上,你可以使用 git reset --hard HEAD^
来实现这个 moving-back-one-step。 HEAD^
表示 "find the first parent of HEAD
",如果 HEAD
命名提交 M
(确实如此)- 表示最右边的上行提交,这是您想要 b运行ch指向。 git reset
命令执行 b运行ch 的 re-pointing,还有 re-sets 你的索引和 work-tree(这样一切都在新提交上干净利落) .
我刚刚花了最后几个小时来解决因将 big-feature-branch-B
合并到 big-feature-branch-A
而导致的合并冲突。我终于完成了,我所有的决议都已上演并准备好投入使用。但是,我工作的流程是:
- 创建
big-feature-branch-A
的分支(我将此分支称为AB-merge-branch
) - 将
big-feature-branch-B
合并到AB-merge-branch
- 创建一个 PR 以将
AB-merge-branch
合并到big-feature-branch-A
,以便决议可以通过代码审查。
当我解决合并冲突的大部分过程时,我意识到我是在 big-feature-branch-A
而不是合并分支中解决它们。
我的问题是,如何在提交更改之前安全地更改分支?
我相信答案很简单,通常我只是隐藏我的更改,切换分支,然后弹出我的更改。但是,我从来没有在合并过程中这样做过,在这种情况下,我对 "trying it" 感到非常不安,因为我不想冒险不得不再次解决所有这些冲突,而且我也不是对我的 git-fu 超级自信。我也读过类似 this 的恐怖故事(但也许我的情况不同,因为我已经解决了所有的冲突,并且所有的变化都是上演的?),并且不想在这种情况下进行试验。谢谢!
首先,简单地完成合并和提交。这样你就不会丢失任何东西。
这是本地操作,不会被其他人看到。
从该提交中,您可以创建分支 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
简短的回答是你不能 (switch b运行ches ... Git):
$ git checkout -b newbr
foo.txt: needs merge
error: you need to resolve your current index first
您的索引处于这种特殊的 "merging" 状态,因此您也无法存储。幸运的是,没有必要这样做。 (如果你解决所有问题,然后 运行 git checkout -b newbr
并提交,你会得到一个 non-merge 提交。你可以使用它,但我们不要那样做。)
您应该做的是继续并完成合并:这将为您提供所需的合并 结果。然后你可以 re-start 在你想要的 b运行ch 合并,并获取你刚刚提交的结果作为 result 你想要,如果有必要的话。然后您完全丢弃原始合并提交(如果需要)。 (如果您不小心破坏了成功的合并 git checkout -b
,这也是您需要做的,几乎如上所示。)
在某些情况下——包括你的情况——原始合并的parent链接就是你想要的,这只是重新[=79=的问题]标记合并。
我会先展示食谱,然后再解释为什么它有效:
... 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
所说的那样,您 "on branch 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 b运行ch(HEAD
记住的那个):
o--...--o--o <-- big-feature-branch-A
/ \
--* M <-- AB-merge-branch (HEAD)
\ /
o--...--o--o <-- big-feature-branch-B
这里没有显示(因为太难显示)是新合并的firstparentM
最右边(latest ) 上行提交,第二行是下行。 (第一和第二的东西以后很重要,如果有的话,当有人想关注 "main" b运行ch vs "side features that were merged in" 时:主要的 b运行ch 总是首先 parent,根据定义。)
您忘记创建一个新的 b运行ch name,所以现在发生的是:
o--...--o--o
/ \
--* M <-- big-feature-branch-A (HEAD)
\ /
o--...--o--o <-- big-feature-branch-B
第一个 parent 是 仍然是 top-and-right-most 提交,第二个 parent 仍然是底部这样的提交。新的合并提交 M
完全相同 。只是 label 移动,指向新的合并 M
,是 big-feature-branch-A
(那个是 HEAD),而不是不存在的 AB-merge-branch
(这显然不是 HEAD)。
所以您现在要做的就是创建您想要的标签。使新 b运行ch 名称 AB-merge-branch
指向 M
的任何内容都足以满足该部分的要求。您可以使用 git checkout -b AB-merge-branch
或 git branch AB-merge-branch
来做到这一点。
如果你确实使用 git checkout -b
,你现在必须 返回 到 big-feature-branch-A
以使用 git reset
修复它(还有其他您可以使用的命令,但我在这里坚持使用 reset
)。如果您使用 git branch
创建新的 b运行ch,您的 current b运行ch 不受干扰:您仍在 big-feature-branch-A
.
无论如何,您希望这个 big-feature-branch-A
b运行ch 名称后退一步,到 M
的第一个 parent,就好像它有一开始就没有前进到 M
。所以你回到(或继续)这个 b运行ch。一旦你在这个 b运行ch 上,你可以使用 git reset --hard HEAD^
来实现这个 moving-back-one-step。 HEAD^
表示 "find the first parent of HEAD
",如果 HEAD
命名提交 M
(确实如此)- 表示最右边的上行提交,这是您想要 b运行ch指向。 git reset
命令执行 b运行ch 的 re-pointing,还有 re-sets 你的索引和 work-tree(这样一切都在新提交上干净利落) .