这个微不足道的合并出了什么问题?

What went wrong in this trivial merge?

编辑:这在 Whosebug 上肯定不是好的做法,我真诚地道歉,但似乎我不清楚我正在做的具体步骤,造成混乱。因此,我决定重写 post 并更清楚地说明我使用了哪些命令 运行 以及重现我的体验的顺序。

因为之前要处理Mercurial中的伪合并,所以做了个小实验:

cd example
hg init

创建example.dart

num add(num a, num b) {
  return a - b;
}
hg add .\example.dart
hg commit -m "bogus add()"
hg branch other

添加到 example.dart:

num sub(num a, num b) {
  return a - b;
}
hg commit -m "correct sub()"
hg update default
hg commit -m "fix add()"

(note by me: Mercurial messes up some characters)
hg log -G
@  ─nderung:        2:19a3c127981b
|  Marke:           tip
|  Vorgõnger:       0:ac1d30ac2dda
|  Nutzer:          Marvin
|  Datum:           Mon Jul 01 19:31:24 2019 +0200
|  Zusammenfassung: fix add()
|
| o  ─nderung:        1:645416c58a38
|/   Zweig:           other
|    Nutzer:          Marvin
|    Datum:           Mon Jul 01 19:23:40 2019 +0200
|    Zusammenfassung: correct sub()
|
o  ─nderung:        0:ac1d30ac2dda
   Nutzer:          Marvin
   Datum:           Mon Jul 01 19:19:47 2019 +0200
   Zusammenfassung: bogus add()

hg update other
hg graft 19a3c127981b

hg log -G
@  ─nderung:        3:567c99a23b17
|  Zweig:           other
|  Marke:           tip
|  Vorgõnger:       1:645416c58a38
|  Nutzer:          Marvin
|  Datum:           Mon Jul 01 19:31:24 2019 +0200
|  Zusammenfassung: fix add()
|
| o  ─nderung:        2:19a3c127981b
| |  Vorgõnger:       0:ac1d30ac2dda
| |  Nutzer:          Marvin
| |  Datum:           Mon Jul 01 19:31:24 2019 +0200
| |  Zusammenfassung: fix add()
| |
o |  ─nderung:        1:645416c58a38
|/   Zweig:           other
|    Nutzer:          Marvin
|    Datum:           Mon Jul 01 19:23:40 2019 +0200
|    Zusammenfassung: correct sub()
|
o  ─nderung:        0:ac1d30ac2dda
   Nutzer:          Marvin
   Datum:           Mon Jul 01 19:19:47 2019 +0200
   Zusammenfassung: bogus add()

这会在 example.dart 中产生预期的结果:

num add(num a, num b) {
  return a + b;
}

num sub(num a, num b) {
  return a - b;
}
hg update default
hg merge other
hg commit -m "merge with other"

hg log -G
@    ─nderung:        4:a76695f39931
|\   Marke:           tip
| |  Vorgõnger:       2:19a3c127981b
| |  Vorgõnger:       3:567c99a23b17
| |  Nutzer:          Marvin
| |  Datum:           Mon Jul 01 19:37:18 2019 +0200
| |  Zusammenfassung: merge with other
| |
| o  ─nderung:        3:567c99a23b17
| |  Zweig:           other
| |  Vorgõnger:       1:645416c58a38
| |  Nutzer:          Marvin
| |  Datum:           Mon Jul 01 19:31:24 2019 +0200
| |  Zusammenfassung: fix add()
| |
o |  ─nderung:        2:19a3c127981b
| |  Vorgõnger:       0:ac1d30ac2dda
| |  Nutzer:          Marvin
| |  Datum:           Mon Jul 01 19:31:24 2019 +0200
| |  Zusammenfassung: fix add()
| |
| o  ─nderung:        1:645416c58a38
|/   Zweig:           other
|    Nutzer:          Marvin
|    Datum:           Mon Jul 01 19:23:40 2019 +0200
|    Zusammenfassung: correct sub()
|
o  ─nderung:        0:ac1d30ac2dda
   Nutzer:          Marvin
   Datum:           Mon Jul 01 19:19:47 2019 +0200
   Zusammenfassung: bogus add()

历史现在看起来像预期的那样。但是,合并结果没有:

num add(num a, num b) {
  return a + b;
}

num sub(num a, num b) {
}

有趣的是,合并算法干净地切掉了 sub() 的主体,同时没有产生任何冲突。

实验是在一台 Windows 10 机器上完成的,机器上新安装了 Mercurial 4.9.1。唯一安装的差异工具是 KDiff3,它随 Mercurial 和 TortoiseHg(我没有使用)一起提供。没有更改标准设置,也没有激活任何插件。

也许这只是一些奇怪的极端情况,但我很想知道是什么原因造成的。如果您能提供任何见解,我将非常高兴。像这样的虚假合并会引起巨大的头痛,因此我认为这是相关的。

我无法重现您的经历。这是我的尝试:

$ mkdir hg
$ cd hg
$ hg init
$ cat > exp.lang << 'end'
> num add(num a, num b) {
>   return a - b;
> }
> end
$ hg add exp.lang
$ hg commit -m initial
$ hg branch other
marked working directory as branch other
(branches are permanent and global, did you want a bookmark?)
$ cat >> exp.lang << 'end'
> 
> num sub(num a, num b) {
>   return a - b;
> }
> end
$ hg commit -m 'add sub()'
$ hg checkout default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ ed exp.lang
42
2
  return a - b;
s/-/+/
w
42
q
$ hg commit -m 'fix bug'

据我所知,这就是你所说的:修复默认分支上的错误。让我们移植修复程序,看看它看起来是否正确:

$ hg checkout other
$ hg graft -r 2
grafting 2:2670b3299c96 "fix bug" (tip)
merging exp.lang
$ hg lga                 # lga is a graphical log alias
@  3:811f4d1a7dc4:draft  other tip Chris Torek
|  fix bug (54 seconds ago)
|
| o  2:2670b3299c96:draft  Chris Torek
| |  fix bug (54 seconds ago)
| |
o |  1:a780b1c8c579:draft  other Chris Torek
|/   add sub() (112 seconds ago)
|
o  0:b085834fc520:draft  Chris Torek
   initial (3 minutes ago)

$ cat exp.lang
num add(num a, num b) {
  return a + b;
}

num sub(num a, num b) {
  return a - b;
}

到目前为止一切顺利 - 据我所知,我已经复制了您的设置。现在:

$ hg checkout default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge other
warning: conflicts while merging exp.lang! (edit, then use 'hg resolve --mark')
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon

合并失败,因为 Mercurial 需要人工帮助。这是 Mercurial 看到的:

$ cat exp.lang
num add(num a, num b) {
<<<<<<< working copy
  return a + b;
||||||| base
  return a - b;
=======
  return a + b;
}

num sub(num a, num b) {
  return a - b;
>>>>>>> merge rev
}

文件的基本副本,从修订版 0 开始,有错误:add returns a - b。当前(默认)分支的提示,版本 2,如下所示:

$ hg abort
aborting the merge, updating back to 2670b3299c96
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat exp.lang
num add(num a, num b) {
  return a + b;
}

这是我们应该期待的:错误已修复。我们要合并的修订版具有相同的 one-line 修复, 还在最后的右大括号之前插入了所有其他内容——额外的四行。 VCS 应该使用哪一种,单线修复还是五线修复?它不知道,所以它停下来寻求帮助。

Mercurial (TortoiseHG) 4.9.1,与@torek 写的结果相同

合并失败的 THG 版本

% hg merge --config=ui.merge=:merge --verbose 3
resolving manifests
merging functions.c
warning: conflicts while merging functions.c! (edit, then use 'hg resolve --mark')
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon

和(预期的)文件在进程中间的状态(在上述合并之后立即)

num add(num a, num b) {
  return a + b;
<<<<<<< working copy
=======
}

num sub(num a, num b) {
  return a - b;
>>>>>>> merge rev
}

加法

这个合并不能non-conflicting合并 for usual merge-tools (GUI presentation will be better这里)

因为灰色字符串/(1)om screenshot/在merge-result冲突区,which(conflict)必须解决 以任何方式。但是,如果我们假设在观察 "other" 文件后(merge-panel 的 right-side,屏幕截图上的 (2) 区域)和您描述的结果

num sub(num a, num b) {
}

你的默认merge-tool可以是工具,它决定自己的政策,而不是解决,它可以是回答问题 "Why it happened".

稍微深一点:如果你的默认 merge-tool 是 "internal:other",那么

  • 来自 "other side" 的绿色部分 (2) 必须出现在 merge-result 中(根据选择 mergetool 的要求)
  • Conflict-area (1) 刚刚忽略
  • 右括号 } (3) 是合并双方的公共块,并转移到 merge-result