Mercurial マージの素晴らしさ - 私に足りないものは何ですか?
-
25-09-2019 - |
質問
Mercurial をしばらく使っていますが、何度も言われる「事実」があります。
実は、昨日フォックリークが作ったビデオを見ていて思いつきました。 このビデオ:フォグクリーク窯:あなたの会社のために DVCS の力を解き放ちます ここで私にとってうまくいかないものがあるようです。
このビデオの 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 つの変更を行いました。
- Function1 関数をファイルの最後に移動しました
- Function1内のメッセージを変更しました
次にマージしようとすると、Mercurial はマージ競合ウィンドウを表示して、私が何をしたのかを把握しようとしました。
基本的に、Function2 のテキストを変更しようとします。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:
例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);
}
例3.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");
}
解決
さて、あなたは現在の制限のいずれかを打っている基本的には、ANY現在のVCS(DVCSかどうか、それは問題ではない)。
事は彼らのマージアルゴリズムのベースは、テキストの差分である、VCSは、現在の言語に依存しないということです。それは、彼らがどのような変化とどのように関連するのコンテキストはのあるを探していることを意味します。
ここでの重要な部分は、コンテキストです。それはあなたが行った変更前と後のいくつかの行ということの何物でもありません。
この手段。
一般的に、あなたの例では、二つの機能を切り替えることによって、あなたは完全に2つのチェンジの間にコンテキストを反転しないだけではなく、悪いことに、最新機能の後に余分なラインを持たないことで、あなたはチャンスを減少させる、暗黙のうちに最新の変更のコンテキストを削減しましたマージアルゴリズムは、あなたが本当に何をしたかを把握することができましたこと。
私は現在、あなたの変更だけではなく、そのテキスト表現ののセマンティックの対処しようとしていること、XMLのために、MSFTから、1つの差分ツールについて知っている。
私はまた、PlasticSCMの男は、いくつかの主流の言語のため、このような機能を実装しようとしていることを知っているが、それは本当に改善の余地があるところです。