Git合并策略:空格使默认显示没有冲突并带来意想不到的结果 [英] Git merge strategies: spaces make default shows no conflict and bring unexpected results
问题描述
a - > 经过多次试验后,我得到了这个简单的测试用例场景: b - > c - (主)
\\
- > d - > b' - > e(分行)
其中:
-
b'
是一个樱桃选择b
-
e
是来自master
的 merge 。
c
和<$ code> c 对相同文件的修改与 b
( d
可能不会' )$ b
假设他们所有人都在处理同一个文件 foobar.txt
。这是文件在每个提交中的外观:
// ----------- a
foo
delme
bar
// ----------- b
foo
delme
新
bar
// ----------- c
foo
新
bar
// ----------- b'
foo
delme
新
bar
// ------------ e
foo
新
新
bar
现在,这是我刚刚进行的简短测试,使用确切设置。
如果您删除了所有 空格 ,那么没有这样的问题。正如我所料,合并只会引发冲突。但我不认为使用任何空格的-X设置是我们在这里寻找的东西......或者它是什么?
同时,在我的生产代码中,这就是我开始研究这一切的原因,而且空白的空间也不是很多,我看到 e
看起来像这样:
// ----------- e
foo
delme
新
bar
所有与 merge从不指责任何冲突!
如果git在这里执行任何它的voodoo神奇的自动合并,这是我期望它看起来的样子例如:
// ----------- e
foo
新
bar
但这也不会发生。
作为免责声明的一部分...
我也试过,但我无法真正理解合并策略下的太多要点。另外,它并没有真正说明 resolve 策略在底层做了什么,例如:
它试图仔细检测交叉的合并歧义,并且通常被认为是安全和快速的。
没有说什么。
有关默认递归的文本较大,但我也无法从中提取足够的信息:
据报道,这会导致更少的合并冲突,而不会导致从Linux 2.6内核开发历史记录中进行的实际合并提交所做的测试错误合并。
已报告?所以我们得到了一个很重的单元测试,并且通过一些报告假设它是正确的?
好吧,这对我来说太模糊了。
我认为我必须做错事!所以,我该怎么做对不对?
我需要做些什么来恢复合并,而不用担心?
基本问题是没有任何形式化的模型去做正确的自动化合并,在每种情况下做正确的事情。事实上,合适的东西可能因合并算法不知道的方式而在不同的用例中有所不同。有很多尝试提出一种正确的合并算法(各种单调合并策略,Codeville,Precise Codeville,Darcs等),并且它们都以某种方式失败真实世界的用例。因此,对于真实世界的合并算法,它在一个真正的代码库上运行得非常好,并且有很多合并重新能够做到。这意味着你永远不应该盲目信任干净的自动合并的结果;虽然它可能没有冲突地干净地合并,但这可能并不完全符合您的预期。您仍然需要查看合并的内容,然后测试结果。
我的一般方法是尝试一些不同的合并选项,就像您一样,查看是否其中一个产生正确的合并。如果这不起作用来让你获得正确的合并(或者产生可以解决的适当冲突的合并),那么你应该做 git merge --no-commit
,并在提交之前根据需要修改合并。
After many trials, I got this simple test case scenario:
a --> b --> c -- (master)
\ \
--> d --> b' --> e (branch)
Where:
b'
is a cherry pick ofb
e
is a merge frommaster
.
b'
was done after c
and c
has modifications to same files as b
(d
probably doesn't matter).
e
can easily look very unexpected.
Let's say all of 'em are dealing with same file "foobar.txt
". This is how the file looks in each commit:
// ----------- a
foo
delme
bar
// ----------- b
foo
delme
new
bar
// ----------- c
foo
new
bar
// ----------- b'
foo
delme
new
bar
// ------------ e
foo
new
new
bar
Now, this was from my brief test just now, with this exact setup.
If you remove all spaces there, there is no such problem. Merge will just accuse a conflict, as I'd expect. But I don't think using any -X setting for spaces is what we're looking for here... Or is it?
Meanwhile, on my production code, which was the reason I began researching about all this, and which has not nearly as many blank spaces, I got to see e
looking something like this instead:
// ----------- e
foo
delme
new
bar
All that happens with merge never accusing any conflict!
If git was to do any of its voodoo magical auto merge here, this is what I'd expect it to look like:
// ----------- e
foo
new
bar
But this also does not happen.
As a bit of a disclaimer...
I also tried reading the f manual, but I can't really understand too many points under merge strategies. Plus it doesn't really say what the resolve
strategy is doing under the hood, for instance:
It tries to carefully detect criss-cross merge ambiguities and is considered generally safe and fast.
That says nothing.
The text about the default recursive
is bigger, but I also couldn't extract enough info from it:
This has been reported to result in fewer merge conflicts without causing mis-merges by tests done on actual merge commits taken from Linux 2.6 kernel development history.
Reported? So we got 1 very heavy unit test and assumed by a few reports it's all right?
Well, it's all too vague to me.
I think I must be doing something wrong! So, how can I do it right?
What need I do to get back on merging with no worries?
The basic problem is that there is no formal model for what it means to do correct automated merges that do the right thing in every case. In fact, "the right thing" can differ for different use cases in ways which the merge algorithm has no idea about. There have been a variety of attempts to come up with a single, correct merge algorithm that always does the right thing (various Monotone merge strategies, Codeville, Precise Codeville, Darcs, and so on), and all of them fail in some way in real-world use cases.
So, for a real-world merge algorithm "it works pretty well on a real codebase with lots of merges" is about the best you're going to be able to do. This means that you should never blindly trust the outcome of a clean automated merge; while it may have merged cleanly without conflicts, that may not have done exactly what you expected. You still need to review what the merge did, and test the result.
My general approach is to try a couple of different merge options, like you did, to see if one of them produces the correct merge. If that doesn't work to get you the correct merge (or a merge that produces the appropriate conflict that you can resolve), then you should do git merge --no-commit
, and fix up the merge as appropriate before committing it.
这篇关于Git合并策略:空格使默认显示没有冲突并带来意想不到的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!