水星合并真棒-我想念的是什么? [英] Mercurial merge awesomeness - what am I missing?

查看:101
本文介绍了水星合并真棒-我想念的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Mercurial已有一段时间了,并且多次给出一个事实".

I've been using Mercurial for a while, and there's one "fact" that is given many times.

实际上,它是在昨天观看Fogcreek制作的视频时打给我的,此视频:Fog Creek窑炉:为您的公司释放DVCS的力量,这里似乎有些东西对我不起作用.

In fact, it hit me while watching a video made by Fogcreek yesterday, this video: Fog Creek Kiln: Unlock the power of DVCS for your company that there seems to be something that doesn't work for me here.

在该视频及其之后的大约1:39,它的观点是,尽管其他版本控制系统跟踪修订(即快照),但DVCS像Mercurial跟踪变更集(即快照之间发生了什么).

At around 1:39 in that video and onwards it makes a point of saying that while other version control systems tracks revisions (ie. snapshots), DVCS' like Mercurial track changesets (ie. what happened between the snapshots.)

这使它们在合并方案中具有优势,然后显示了一个示例.如果您在一个分支中移动一个函数,然后在另一个分支中更改相同的函数,Mercurial可以将其合并.

This gives them an edge in merging scenarios, and then it shows an example. If you move a function in one branch, and change the same function in another branch, Mercurial is able to merge that.

尽管我现在找不到任何直接链接,但我在其他地方也看到了这一点.

And I've seen this mentioned elsewhere, though I can't find any direct links now.

这似乎对我不起作用.

对于TortoiseHg,默认的"beyondcompare3"合并工具配置存在此问题.我将以下配置添加到我的Mercurial.ini文件中,现在可以正常使用了.当然,如果它不能自动合并,它将跳至GUI工具,但是现在此问题中描述的合并在没有任何提示的情况下即可运行,并且开箱即用就正确了.

[ui]
merge = bc3

[merge-tools]
bc3.executable = C:\Program Files (x86)\Beyond Compare 3\bcomp.exe
bc3.args = $local $other $base $output /automerge /reviewconflicts /closescript
bc3.priority = 1
bc3.premerge = True
bc3.gui = True


为了对此进行测试,我将该文件提交到存储库中:


To test this, I committed this file to a repository:

void Main()
{
    Function1();
    Function2();
}

public void Function1()
{
    Debug.WriteLine("Function 1");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}

然后从这个分支中分支出两个不同的并行变更集,我做了以下两个变更:

Then in two different parallel changesets branching out from this one, I did the following two changes:

  1. 我将Function1函数移到了文件的底部
  2. 我更改了Function1内部的消息

然后我尝试合并,Mercurial给了我一个合并冲突窗口,试图弄清楚我做了什么.

I then tried to merge, and Mercurial gives me a merge conflict window, trying to figure out what I did.

基本上,它会尝试更改Function2中的文本,该文本现在位于Function1移动之前的位置.

Basically, it tries to change the text in Function2, which is now in the position that Function1 was before it was moved.

这不应该发生!

以下是用于重现我的示例的源文件:

Here's the source files for reproducing my example:

用于生成存储库的批处理文件:

Batch file for producing repository:

@echo off

setlocal

if exist repo rd /s /q repo
hg init repo
cd repo

copy ..\example1.linq example.linq
hg commit -m "initial commit" --addremove --user "Bob" --date "2010-01-01 18:00:00"

copy ..\example2.linq example.linq
hg commit -m "moved function" --user "Bob" --date "2010-01-01 19:00:00"

hg update 0
copy ..\example3.linq example.linq
hg commit -m "moved function" --user "Alice" --date "2010-01-01 20:00:00"

文件的3个版本,例如example1.linq,example2.linq和example3.linq:

The 3 versions of the file, example1.linq, example2.linq and example3.linq:

Example1.linq:

Example1.linq:

<Query Kind="Program" />

void Main()
{
    Function1();
    Function2();
}

public void Function1()
{
    Debug.WriteLine("Function 1");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}

Example2.linq:

Example2.linq:

<Query Kind="Program" />

void Main()
{
    Function1();
    Function2();
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}

public void Function1()
{
    Debug.WriteLine("Function 1");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

Example3.linq:

Example3.linq:

<Query Kind="Program" />

void Main()
{
    Function1();
    Function2();
}

public void Function1()
{
    Debug.WriteLine("Function 1b");
    for (int index = 0; index < 10; index++)
        Debug.WriteLine("f1: " + index);
}

public void Function2()
{
    Debug.WriteLine("Function 1");
}

推荐答案

好吧,您目前遇到的基本上是任何当前VCS的限制之一(是否为DVCS,这都没有关系).

Well, you're currently hitting one of the limitation of, basically, ANY current VCS (DVCS or not, it does not matter).

问题在于,VCS当前与语言无关,它们的合并算法的基础是文本差异.这意味着他们正在寻找什么变化以及与之相关的上下文.
这里的重要部分是上下文.所做的更改前后仅需几行.

The thing is that VCS are currently language agnostic, the base of their merge algorithm is a textual diff. It means that they are looking for what change and what is the related context.
The important part here is the context. It is nothing more that some lines before and after the changes you made.

这意味着它们在处理同一文件内部的代码重组方面真的很糟糕,因为您基本上是在搞砸它们可以依赖的所有上下文.
通常,在您的示例中,通过切换两个功能,您不仅会完全颠倒两个变更集之间的上下文,而且更糟糕的是,由于在最新功能之后没有多余的行,因此隐式减少了最新变更的上下文,从而减少了机会合并算法就能弄清楚您的实际工作.

This means that they are really bad at dealing with code re-organisation inside of a same file, because you're basically screwing all the context they can rely on.
Typically, in your example, by switching the two functions, you not only completely inverted the context between the two changesets, but worse, by having no extra lines after the latest function, you reduced implicitly the context of the latest change, diminishing the chances that a merge algorithm got able to figure out what you really did.

我目前仅从msft那里了解一种针对XML的差异工具,该工具试图处理更改的语义,而不仅仅是文本表示.
我也知道,PlasticSCM的人正在尝试为某些主流语言实现这种功能,但这确实是一个仍有改进空间的地方.

I currently only know about one diff tool, from msft, for XML, that is trying to deal with the semantic of your change and not just its textual representation.
I also know that the guys of PlasticSCM are trying to implement such feature for some mainstream languages, but it is really a place where there is room for improvement.

这篇关于水星合并真棒-我想念的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆