19

それが話題になる前に、私はすでにこのトピックに関するいくつかのスレッドを見てきました。

開発グループを (Subversion から) Mercurial に切り替えることを検討しています。その前に、通常の賛否両論のリストを作成しています。

私の「長所」の 1 つは、マージが Mercurial の方が優れていることですが、これまでのところ、説得力のある証拠を見つけることができていません。つまり、HgInit.com で確認できなかった声明があります。

たとえば、関数を少し変更してから別の場所に移動した場合、Subversion はそれらの手順を実際には覚えていないため、マージの時期になると、新しい関数が突然現れたと考える可能性があります。 . Mercurial はこれらのことを個別に記憶します: 関数の変更、関数の移動。つまり、その関数も少し変更した場合、Mercurial が変更を正常にマージする可能性が高くなります。

これは非常に魅力的な機能ですが、私が知る限り、それはただの熱気です。上記の記載については確認できませんでした。

Mercurial リポジトリを作成し、Hello World を実行してからクローンを作成しました。1 つでは、関数を変更し、コミットしてから移動し、コミットしました。もう1つは、関数に別の出力行を追加してコミットしただけです。

マージすると、Subversion を使用した場合と基本的に同じマージ競合が発生します。

Mercurial はファイルの名前変更をより適切に追跡できること、および DVCS にはマージ以外にも利点があることは理解していますが、この例に興味があります。ジョエル・スポルスキーはここに基地外ですか、それとも何か足りないのですか?

私はこの分野の経験はありませんが、Mercurial はより多くの情報を保持しているため、理論的にはマージがうまくいくようです (開発者も頻繁にチェックインを行った場合)。たとえば、Mercurial が複数の変更を比較してコンテキストの変更を取得することは実行可能であると考えています。たとえば、関数を変更し、チェックインし、関数を移動し、チェックインすると、Mercurial はこれら 2 つの部分を関連付けます。

ただし、Mercurial のマージは、追加された情報を実際に利用していないようで、Subversion と同じように動作しているようです。これは正しいです?

4

3 に答える 3

6

私の知る限り、Mercurial がファイル サイズ未満のチャンクでコードの移動を追跡すると言う人は、まったく間違っています。コードの変更と別にファイルの名前変更を追跡するため、Dave がファイルの名前を変更し、Helen がファイル内の何かを変更した場合、それを自動マージできますが、私の知る限り、Subversion もそれを行うことができます! (CVS はできません。)

しかし、Mercurial のマージ ロジックが Subversion のマージ ロジックよりも劇的に優れている点があります。それは、競合の解決を記憶することです次の履歴グラフを検討してください。

base ---> HELEN1 ---> merge1 --> HELEN2 -> merge2
     \--> DAVE1 ---/                    /
                   \--> DAVE2 ---------/

Helen と Dave は個別に変更を加えました。Helen は Dave のツリーをプルしてマージし、その上に別の変更を加えました。その間、Dave は Helen から引っ張ることを気にせずにコーディングを続けました。それからヘレンはデイブの木をまた引っ張った。(おそらく Dave はメインの開発トランクに取り組んでいて、Helen は機能ブランチに取り組んでいますが、彼女は定期的にトランクの変更と同期したいと考えています。) 「merge2」を構築するとき、Mercurial は「merge1」で行われたすべての競合解決を記憶します。 Helen の新しい競合のみを表示しますが、Subversion は Helen に最初からマージをやり直させます。(Subversion でこれを行う必要をなくす方法はいくつかありますが、それらはすべて追加の手動ステップを必要とします。Mercurial がそれを処理します。)

詳細については、Monotone 用に開発されたマーク マージ アルゴリズムについてお読みください。また、AFAIK は現在 Mercurial と Git の両方で使用されています。

于 2011-02-12T23:20:50.500 に答える
1

私の知る限り、SVNはすべてのマージを内部で行います.マージツールは、競合がある場合にのみ存在します.(明らかに)競合について通知し、修正する必要があります.

競合しないケースは、パッチの適用に基づいています。つまり、svn はリビジョンで行った変更を取得し、それらをターゲットに適用します。SVN の最近のバージョン (1.5 以降) は、以前に行ったマージを記憶し、この情報をディレクトリに関連付けられたプロパティに保存します。1.6 は、1.5 と比較して、これらのプロパティをより適切に処理します。

SVN は、2 つのツリーを比較してそれらを比較することによってマージしません-本を参照してください-マージするツリーが関連していない場合を除いて、差分タイプのマージ操作を実行します (または --ignore-ancestry オプションを指定します)。 . ここに簡単な説明があります何が起こるか。これは、過去の競合をマージするときに確認できます。トリッキーなリビジョンのマージを解決すると、svn はどのリビジョンがマージされたかを記憶し、それらの変更を再度適用します。試してみることでこれを証明できます-ブランチ、2つのファイルの編集、マージして競合を取得します。分岐ファイルを同じ行でのみ編集してから、マージします。ターゲット ファイルが変更されていなくても、競合が発生しますが、マージによって、分岐ファイルが期待していたものから変更された行に変更が適用されるためです (つまり、変更しようとしている行がどうあるべきかを示すパッチのように)。実際には、マージの変更を繰り返し拒否する傾向がないため、これは表示されません。

ただし、SVN は、名前が変更されたファイルを削除 + 追加操作として追跡するため、適切な処理を行いません。他の SCM はより良い仕事をしますが、ファイルの名前が変更されたのか、削除されて追加されたのか、特にそのファイルが変更された場合は特にわかりません。Git はいくつかのヒューリスティックを使用してこれを判断しようとしますが、それが成功を保証するとは思えません。ファイルシステムにフックする SCM ができるまでは、このままだと思います。

于 2011-02-14T18:03:04.370 に答える
1

2つのこと:

  1. Mercurial にはマージを行うための内部コードがあり、内部の「事前マージ」が失敗した場合にのみ、外部のマージ ツールを呼び出します。

    HG Bookにリンクすると、競合を処理するための組み込みツールはなく(組み込みのマージがないのとは異なります)、Mercurial wikiには、外部を呼び出す前にMercurialが内部的にマージを試みると記載されていますプログラム。

  2. Mercurials が成功し、Subversion がマージに失敗する明示的なケースを示す質問へのリンクです。これは、Mercurial と Subversion の両方で内部マージ コードを使用したすぐに使える比較です。

于 2011-02-22T13:58:04.277 に答える