1

商用開発におけるバージョン管理では、多くの場合、プロジェクトの複数の分岐があります。私のMercurial管理プロジェクトでは、次のように、共通の親から派生した安定バージョンとトランクバージョンをよく使用します。

      V8     (the parent of both V8-stable and V9, revisions 1..100)
       |
       +---  V8_stable  (bug fix branch, revisions 101 to 500 )
       |
       +---  V9_trunk   (trunk, revisions 501 to 1000 )

プロジェクトの上記のすべてのバージョンにはファイルがあり、それを と呼びますhelloworldapp.py。これらのサンプルは、私が知っている最も疑似コードに似た言語である Python で作成されていますが、質問は Python に関する質問ではありません。現在、mercurial では、クローンを使用して分岐したり、Mercurial の組み込みの分岐機能を使用したりできます。この例では、リポジトリ全体のクローンを使用して分岐しています。

helloworldapp.py共通の親リビジョンである V8は次のとおりです。

# helloworldapp.py rev 100 (v8)
def func1(a,b,c,d,e):
    print "stuff"
def func2(a,b,c,d,e):
    func1(a,b,c,d,e)
def func3(a,b,c,d,e):
    func2(a,b,c,d,e)
def func4(a,b,c,d,e):
    func3(a,b,c,d,e)
def func5(a,b,c,d,e):
    func4(a,b,c,d,e)
def func6(a,b,c,d,e):
    func5(a,b,c,d,e)
def func7(a,b,c,d,e):
    func6(a,b,c,d,e)

func7(1,2,3,4,5)

V8-stable ブランチの一部であるリビジョン 500 は次のとおりです。

# helloworldapp.py rev 500 (v8_stable)
def func1(a,b,c,d,e):
    print "stuff"

def morestuff():
   print "morestuff"

morestuff()
func1(1,2,3,4,5)

V9 トランク ブランチのリビジョン 1000 の部分は次のとおりです。

# helloworldapp.py rev 1000 (v9_trunk)
def func1(a,b,c,d,e):
    print "stuff"

def func4(a,b,c,d,e):
    morestuff()
    morestuff()
    morestuff()
    func1(a,b,c,d,e)

def morestuff():
   print "hello"

func4(1,2,3,4,5)

上記のファイルは、ファイル指向のバージョン管理でブランチが同期しなくなったときに発生する状態の非常に短い例であり、「安定した状態からトランクへ」のマージアップを管理する必要があるときに問題を引き起こします (プルとプルを介して)次にマージします)。

マージすると、次のような状況になります。現実の世界では、問題は通常、私にとって約 100 倍から 1000 倍に拡大されることに注意してください。多くの場合、Hg マージでは解決できない 5000 行以上の競合が何百ものファイルで発生し、KDiff3 で各ファイルを手動でマージする必要があります。

ブランチの同期がずれないようにすること以外に、Mercurial ユーザーはこのような状況でマージを簡単にするために何ができるでしょうか? 上で説明した状況では、「ファイルのブランチ A の 6 行目で作業する」ことは「ファイルのブランチ B で 6 行目で作業する」ことと同じであり、行ごとのマージはマージの競合を引き起こします。 2 人のユーザーが、ファイル内の異なる関数を実際に (自分の頭の中で) 作業していました。もう使用されなくなった関数を 1 つのファイルから削除することにより、不要になったため、マージの競合が発生する可能性がほぼ確実になります。「上流の安定したブランチで行を移動したり削除したりしない」などのルールを設定する必要があります。Smalltalk のイメージベースのバージョン管理システムを使っていたら、「何行目だろう?」というアクシデントが起こることを私は知っています。もはやそれに入ることはありません。Mercurial が使用する diff ツールが Python を理解していれば、C# コードではおそらくまったくうまく機能しないという代償を払って、Python コードでより良い仕事をすることができます。したがって、これはファイルベースのプログラミングと DVCS ツールの最先端です。罰金。

したがって、ここに描かれているマージの状況では、

ここに画像の説明を入力

(拡大版はここをクリック)

*私が見ているのは、「morestuff」機能のすべてが必要か、まったく必要ないかを理解できるようにしたいマージ競合です。

ここに画像の説明を入力

私が手に入れたいもの(自動的に):

ここに画像の説明を入力

サンプル リポジトリを bitbucket に次のように投稿しました: helloworldapp_v9 helloworldapp_v8_stable

この「マージの競合を解決しようとしているときに何が起こるかを構築できる最も単純な例」を試すには、上記のいずれかを複製し、もう一方からプルしてからマージします。最後に、私の質問は次のとおりです。Mercurial のプロのユーザーは、この種の状況にどのように対処しますか? この例は不自然であり、DVCS ツールのユーザーが直面する複雑さの一部を示していることを理解してください。ただし、現実の世界では、これらの競合は、ここで示している単純なケースよりもはるかに複雑であることがよくあります。私は、TortoiseHG と KDIFF3 を使用して、ほとんどの小さくて単純な競合をかなり迅速に処理することを学びましたが、マージ地獄は、Subversion や Perforce で覚えているよりもはるかに問題が少ないことがわかりました。(a) プログラマー (私) または (b) 私のツールは、この複雑さを管理および理解するのに役立つすべてのことを行ったと思います。Mercurial を使用するための代替ソリューション、ツール、および作業戦略が存在するように感じますが、それらはまだ試したり学んだりしていません。多分MQとリベース?

4

1 に答える 1

3

実際、私の経験では、現実の世界は通常、次の 2 つの理由からそのようには見えません。

  1. Mercurial が 2 つのブランチ間で物事がどのように適合するかを段階的に認識できるように、はるかに頻繁にマージします (例では v8 から v9 へ)。500 個の変更セットは、1 つのステップでまとめるための多くの変更です (そして、私は以前にそのようにしました!)。

  2. ブランチをマージするとき、変更はあなたの例ほど激しく衝突しません。衝突が少なくなり、各変更を取り巻くコンテキストが増えるため、マージ ツールはそれらをまとめるのにはるかに優れた仕事をします。

衝突は確かにあり、それらを手動でまとめる方法を理解する必要があります。それを先延ばしにすると、大きな頭痛の種になる可能性があります。ただし、これを行うと、共通の祖先はそのマージになり、その衝突を再度確認する必要はありません。より頻繁にマージすることで、共通の祖先以降の変更セットの数を減らします。

V8_stable から V9_trunk への定期的なマージを使用して、例を再実行することに興味があります。関数の定義の間にテキストを追加して、変更を区別するためのコンテキストを hg に与えることにも興味があります。


あなたの例でより頻繁なマージを試みましたが、うまくいきませんでした。バージョンが大きく異なる場合 (同じ 15% ~ 25% のみ)、それらは根本的に異なるコードベースになり、マージはもはや意味がありません。その時点で、私は断片を別々のファイルに分解して、両方のバージョン (および私の正気!) が平和に共存できるようにします。

于 2012-11-21T17:15:47.797 に答える