8

私はしばらく Mercurial を使用してきましたが、何度も言われる「事実」が 1 つあります。

実際、昨日 Fogcreek によって作成されたビデオを見ているときに、このビデオを見ているときに私を襲いました。このビデオ: Fog Creek Kiln: Unlock the power of DVCS for your company .

そのビデオの 1:39 あたり以降では、他のバージョン管理システムがリビジョン (つまり、スナップショット) を追跡するのに対し、DVCS のような Mercurial は変更セット (つまり、スナップショット間で何が起こったのか) を追跡することを強調しています。

これにより、シナリオのマージが有利になり、例が示されます。あるブランチで関数を移動し、別のブランチで同じ関数を変更すると、Mercurial はそれをマージできます。

そして、これは他の場所で言及されているのを見ましたが、今は直接リンクを見つけることができません.

これは私にはうまくいかないようです。


編集: これは、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

これをテストするために、このファイルをリポジトリにコミットしました。

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

次に、この変更セットから派生する 2 つの並行変更セットで、次の 2 つの変更を行いました。

  1. Function1 関数をファイルの末尾に移動しました
  2. Function1 内のメッセージを変更しました

次にマージを試みたところ、Mercurial はマージ競合ウィンドウを表示し、何をしたかを把握しようとしました。

基本的に、移動前の Function1 の位置にある Function2 のテキストを変更しようとします。

こんなはずじゃなかった!


私の例を再現するためのソースファイルは次のとおりです。

リポジトリを生成するためのバッチ ファイル:

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

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

例 2.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");
}
4

1 に答える 1

7

さて、あなたは現在、基本的に、現在のVCS(DVCSかどうかは関係ありません)の制限の1つにぶつかっています。

重要なのは、VCSは現在言語に依存せず、マージアルゴリズムのベースはテキストの差分です。それは、彼らがどのような変化と関連する文脈を探していることを意味します。
ここで重要なのはコンテキストです。変更の前後のいくつかの行に過ぎません。

これは、基本的に信頼できるすべてのコンテキストを台無しにしているため、同じファイル内でのコードの再編成を処理するのが非常に苦手であることを意味します。
通常、この例では、2つの関数を切り替えることで、2つのチェンジセット間のコンテキストを完全に反転させるだけでなく、さらに悪いことに、最新の関数の後に余分な行を追加しないことで、最新の変更のコンテキストを暗黙的に減らし、可能性を減らします。マージアルゴリズムがあなたが実際に何をしたかを理解できるようになったということです。

私は現在、msftからXML用の1つの差分ツールについてしか知りません。これは、テキスト表現だけでなく、変更のセマンティクスを処理しようとしています。
また、PlasticSCMのメンバーが一部の主流言語にこのような機能を実装しようとしていることも知っていますが、実際には改善の余地がある場所です。

于 2010-11-17T10:30:07.763 に答える