Ртутный слияния удивительный - что мне не хватает? - PullRequest
8 голосов
/ 17 ноября 2010

Я уже некоторое время пользуюсь Mercurial, и есть один «факт», который повторяется много раз.

На самом деле, меня поразило, когда я вчера смотрел видео, сделанное Fogcreek, это видео: Fog Creek Kiln: раскройте потенциал DVCS для вашей компании , что, кажется, что-то не работает для меня здесь.

Примерно в 1:39 в этом видео и далее имеет смысл сказать, что в то время как другие системы контроля версий отслеживают изменения (например, моментальные снимки), DVCS ', как наборы изменений Mercurial отслеживают (т.е. что происходило между моментальными снимками).

Это дает им преимущество в сценариях слияния, а затем показывает пример. Если вы переместите функцию в одну ветку и измените ту же функцию в другой ветке, Mercurial сможет объединить это.

И я видел это упомянутое в другом месте, хотя сейчас я не могу найти никаких прямых ссылок.

Кажется, это не работает для меня.


Редактировать: Это проблема со стандартной конфигурацией инструмента слияния "beyondcompare3" для TortoiseHg. Я добавил приведенную ниже конфигурацию в мой файл Mercurial.ini, и теперь он работает как положено Конечно, он будет подключен к инструменту с графическим интерфейсом, если он не сможет автоматически объединиться, но теперь объединение, описанное в этом вопросе, выполняется без каких-либо подсказок и просто выполняет правильные действия из коробки

[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

Чтобы проверить это, я передал этот файл в хранилище:

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");
}

Затем в двух разных параллельных ревизиях, ответвляющихся от этой, я сделал следующие два изменения:

  1. Я переместил функцию Function1 в конец файла
  2. Я изменил сообщение внутри Function1

Затем я попытался слить, и Mercurial выдает мне окно конфликта слияния, пытаясь выяснить, что я сделал.

По сути, он пытается изменить текст в Function2, который теперь находится в положении, в котором Function1 находился до его перемещения.

Этого не должно было быть!


Вот исходные файлы для воспроизведения моего примера:

Пакетный файл для создания репозитория:

@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:

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:

<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:

<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");
}

1 Ответ

7 голосов
/ 17 ноября 2010

Ну, вы в настоящее время сталкиваетесь с одним из ограничений, по сути, ЛЮБОГО текущего VCS (DVCS или нет, это не имеет значения).

Дело в том, что VCS в настоящее время не зависят от языка, основой их алгоритма слияния является текстовая разница. Это означает, что они ищут, какие изменения и с чем связан контекст .
Важной частью здесь является контекст. Это не более, чем некоторые строки до и после внесенных вами изменений.

Это означает, что они действительно плохо справляются с реорганизацией кода внутри одного и того же файла, потому что вы в основном портите весь контекст, на который они могут положиться.
Как правило, в вашем примере, переключая две функции, вы не только полностью инвертировали контекст между двумя наборами изменений, но, что еще хуже, не имея лишних строк после последней функции, вы неявно сокращали контекст последнего изменения, уменьшая шансы что алгоритм слияния смог выяснить, что вы на самом деле сделали.

В настоящее время я знаю только об одном инструменте сравнения, от msft, для XML, который пытается справиться с семантикой вашего изменения, а не только с его текстовым представлением.
Я также знаю, что ребята из PlasticSCM пытаются реализовать такую ​​функцию для некоторых основных языков, но это действительно место, где есть возможности для совершенствования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...