如何停止在Git中合并?

20

我进行了一次三路合并分支的合并:

git checkout master
git merge BranchA

>> Fast-forward merge

git merge BranchB

>> Three-way-merge (prompts for a merge commit message)

我的问题有两个:

  • 我如何中止合并? 通过三方合并,我被展示了写合并提交信息的编辑器。 但是,如果我未保存退出,git 仍会继续合并(只是合并提交信息将变为默认值而不是我本来可以写但取消了的值)

    commit 11111233
        Merge 'BranchB' into master
    

    显然没有确认提交消息,我预计合并不会发生(与我未确认正常提交消息时的行为相同)。

  • 两个合并的分支提交记录是否按时间顺序排序? 或者首先(在git log中),我会看到BranchA的提交,接着才是BranchB的提交?

编辑

为了更好地解释第二个问题,我进行了测试: 从master分支开始的2个分支(A和B)。 我在B上进行了一次提交,然后在A上,然后再在B上,最后再在A上进行了一次提交。 然后我将BranchA合并到master。 然后将BranchB合并到master

但是当我在master上运行git log时,这就是输出结果,也是我问第二个问题的原因:

commit 730fdd4d328999c86fa4d3b6120ac856ecaccab1
Merge: 7eb581b cc1085a
Author: Arthur Conandoyle <Arthur.Conandoyle@live.com>
Date:   Mon Feb 9 21:24:27 2015 +0100

    Merge branch 'BranchB' into master_COPY

commit 7eb581b39a8402e1694cc4bf4eab4a3feb1143f8
Author: Arthur Conandoyle <Arthur.Conandoyle@live.com>
Date:   Mon Feb 9 21:23:18 2015 +0100

    BranchA) - This should be the (second) last change of the branch, and be the
    most recent into the git log, even if I merge another branch into master,
    AFTER the one where we are committing this.

commit cc1085a6aaa2ee4b26d3c3fbb93bee863d9e7c28
Author: Arthur Conandoyle <Arthur.Conandoyle@live.com>
Date:   Mon Feb 9 21:20:29 2015 +0100

    (BranchB) - Add settings to the last new features

commit 5f5b846a2f89886d01244ba77af941f554233b51
Author: Arthur Conandoyle <Arthur.Conandoyle@live.com>
Date:   Mon Feb 9 21:18:54 2015 +0100

    (BranchA) - Add some changes

commit 92a57a56b6b7c9694fbedda71b8070fc58683dde
Author: Arthur Conandoyle <Arthur.Conandoyle@live.com>
Date:   Mon Feb 9 21:18:17 2015 +0100

    (BranchB) - Some changes

commit 221765476e348833cf8da73b1bf5239f3d4240e8
Author: Arthur Conandoyle <Arthur.Conandoyle@live.com>
Date:   Tue Feb 3 12:12:19 2015 +0100

    Change (this is the last commit of the parent 'master' branch)

(正如Srdjan Grubor所写)按照合并的BranchA的提交先于所有提交,然后是合并的BranchB的所有提交,按照合并的顺序排列……但有趣的是,git log显示的是按时间顺序排序的,而提交并没有按分支分组显示!


1
尝试写入“空”消息以中止操作,即删除所有内容并保存为空文件。 - Alexey Ten
不错的建议。这个解决方法规避了问题(我会说是“bug”),并允许中止合并! - Kamafeather
2
这不是一个 bug。空的提交消息会中止提交(除非明确允许);这对所有提交都是适用的:普通的提交和合并提交。如果您将普通的提交消息模板设置为一些初始值,仅退出也不会中止提交。它是提交的内容,而不是您是否更改了某些内容的事实。否则,只接受默认消息是行不通的。 - poke
1
“三路合并”这个术语(在 Git 中)并不是指将 两个 分支合并到当前分支,而是指当把 一个 分支合并到当前分支时,该过程是通过找到“合并基础”(最近的共同祖先)并组合两组变更来完成的:合并基础与 HEAD、合并基础与另一个分支端点。在 Git 中,当 HEAD 是合并基础时,会发生“快进式”合并。 - torek
1
@jthill:如果公共祖先是当前的“HEAD”,git仍将执行双向合并(也称为快进)。至少在read-tree-m选项的文档中已经这样说明了。不确定是否还有其他人使用这个术语... - torek
显示剩余4条评论
4个回答

44

分支B合并非常普通,需要一个普通的提交消息。如果您退出而没有更改它,则会使用默认值完成合并。由于合并本身已成功,现在唯一停止它的方法是提供错误的合并消息(如果没有挂钩,则空消息将起作用),或者拥有可以出错的编辑器,例如我刚学到的 vim 的 :cq

当合并停止时,您可以使用以下命令中止它:

git merge --abort
# or
git reset --merge

如果您误提交了内容,可以使用撤销功能

git reset --hard @{1}

在git中,没有分支“所有权”的概念,您可以引用提交的所有方式都是同级的。

通过git log,您可以更好地了解其展示的结构。

git log --graph --decorate --oneline

尝试使用--date-order--topo-order--all参数。


生成三方合并。两个分支都来自于_master_,如果第一个_merge_是_fast-forward,则第二个合并将是_three-way-merge_,并会要求一个提交信息;我在两个不同的存储库上尝试过。您的解决方案是正确的,但我正在寻找一种中止的方法,而您建议使用git reset @{1}撤消(正如您所说)。 - Kamafeather
关于你的_edit2_: 我在_Git_ _1.7.10.4_和_1.9.3_上尝试了一下,即使你退出编辑器而不保存,两者都会确认_merge_。为了获得正确的行为,您需要提供一个空消息并将其提交(正如Alexey Ten在评论中建议的那样);然后它将按预期运行,合并将是不完整的。仅仅退出编辑器而不保存是不够的,它仍然会确认合并,并使用默认文本作为_merge_消息。 - Kamafeather
@Kamafeather:jthill 正在谈论第一个合并,即作为快进完成的那个。那个合并已经完成了。写一个空提交消息会中止第二个合并,但第一个合并已经完成了。 - torek
您将获得一个默认的合并消息。不保存退出将接受该消息并完成合并。编辑:这是有意为之的,因为默认消息迄今为止是最常见和最好的选择。我认为您可能正在使用已经废弃的“三方合并”的意义。虽然合并会将两个提示与原始文件进行比较,因此涉及到三个文件,但人们认为它在使用中更好。如今只计算提示可以减少误导。 - jthill
@torek:感谢您的澄清。然而,我并没有预料到第二个_merge_的中止也会撤销第一个_merge_。我放置了第一个_branch/merge_只是为了举一个具体的例子,说明当我尝试合并从同一父分支开始的第二个分支时会发生什么。 jthill: 感谢您的澄清 :) - Kamafeather

2
关于您的编辑,git log会对其输出进行排序。即使在线性历史中,这也可能令人惊讶。有标志可以更改排序方法,添加--graph将默认排序更改为--topo-order
另一个值得注意的问题是,当git快进分支时,没有合并提交:
      C---D   <-- branch
     /
A---B         <-- mainline

允许mainline通过快进方式获取branch会导致简单图形:

      C---D   <-- mainline, branch
     /
A---B

这可以轻松地画成一条简单的直线,但是通过强制使用合并提交(git merge --no-ff)会产生一个实际的双亲合并提交:

      C---D   <-- branch
     /     \
A---B-------M <-- mainline

一旦推广到有更多提交的情况下,这将为提交排序过程提供更多有趣的选择。


感谢您的解释和提供文档链接。我应该先检查一下!我不知道 git log 有排序选项,还有默认排序。 - Kamafeather

0

在你完成并使用后,你可以“中止”合并。

git reflog

返回到之前的树状态。通常合并不是按照时间顺序排序,而是按照分支提交顺序排序,然后再单独排序。这意味着您会看到您的合并提交,然后是所有源分支提交(按照时间顺序),然后是您的主分支提交(按照时间顺序)。


你说的和我预期的一样...但是我尝试了一下,发现行为不同!请查看我回答顶部的编辑 - Kamafeather

0

这个命令将帮助您中止本地合并:

git merge --abort

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接