Mercurialの方がSubversionよりも分岐とマージが簡単なのはなぜですか?


92

SubversionまたはCVSでブランチへの複数のマージを処理することは、経験しなければならないことの1つにすぎません。Mercurial(およびおそらく他の分散システム)でブランチとマージを追跡するのは非常に簡単ですが、理由はわかりません。他に誰か知っていますか?

私の質問は、MercurialではSubversions / CVSの中央リポジトリと同様の作業方法を採用でき、すべてが正常に機能するという事実に由来します。同じブランチで複数のマージを行うことができ、コミット番号とタグ名を含む紙の無限のスクラップは必要ありません。

Subversionの最新バージョンにはブランチへのマージを追跡する機能があるので、同じ程度の手間はかかりませんが、それは彼らの側での巨大で大きな開発であり、それでも開発チームが行うすべてのことを行うわけではありませんそれが好きです。

すべてが機能する方法には根本的な違いがあるはずです。

回答:


115

Subversion(およびCVS)では、リポジトリが何よりも重要です。gitとmercurialでは、実際には同じようにリポジトリの概念はありません。ここでは、変更が中心的なテーマです。

+1

CVS / SVNの面倒は、これらのシステム が変更の親子関係を覚えていないという事実から来てます。GitとMercurialでは、コミットは複数の子を持つことができるだけでなく、複数の親を持つこともできます!

それは簡単にグラフィカルなツールのいずれかを使用して観察し、することができますgitkhg view。次の例では、ブランチ#2はコミットAで#1から分岐され、それ以降1回マージされています(Mで、コミットBとマージされています)。

o---A---o---B---o---C         (branch #1)
     \       \
      o---o---M---X---?       (branch #2)

AとBには2つの子があり、Mには2つの親があります。これらの関係はリポジトリに記録されます。ブランチ#2のメンテナがブランチ#1からの最新の変更をマージしたい場合、次のようなコマンドを発行できます。

$ git merge branch-1

そして、ツールはベースがBであることを自動的に認識します。これは、#2の先端の祖先であるコミットMで記録されたためであり、BとCの間で起こったことをマージする必要があることを示します。CVSはこの情報を記録しません。 、バージョン1.5より前のSVNも同様でした。これらのシステムでは、グラフは次のようになります。

o---A---o---B---o---C         (branch #1)
     \    
      o---o---M---X---?       (branch #2)

ここで、Mは、AとBの間で発生したすべての巨大な「押しつぶされた」コミットであり、Mの上に適用されます。証書が実行された後、Mの場所の痕跡が残っていないことに注意してください(人間が読めるコメントを除く)どれだけ多くのコミットがまとめて崩壊したのからではなく、歴史をはるかに突き抜けることができませんでした。

さらに悪いことに、2番目のマージの実行は悪夢になります。最初のマージの時点でのマージベースが何であったかを理解する 必要があります(そして、最初にマージがあっこと知る必要があります!) Mの上でA..Bを再生しようとしないように、ツールに情報を提供します。これらすべては、緊密なコラボレーションで作業する場合には十分に困難ですが、分散環境では単純に不可能です。

(関連する)問題は、「XにBが含まれていますか?」という質問に答える方法がないことです。ここで、Bは潜在的に重要なバグ修正です。それでは、マージ時にその情報がわかっているので、その情報をコミットに記録しないでください。

P.-S. -私はSVN 1.5+マージレコーディング機能の経験はありませんが、ワークフローは分散システムよりもはるかに不自然なようです。それが実際に当てはまる場合は、おそらく上記のコメントで述べたように、変更自体ではなくリポジトリの編成に重点が置かれているためです。


6
SVN 1.5+は確かに、SVNプロパティをマージコミットMに追加し、そこに含まれるマージされたコミット、つまりABをリストします。だからあなたは同じ情報を持っています。
Simon D

やや。技術的には、SVNのマージ追跡は、Gitが「チェリーピッキング」と呼んでいるものに似ており、ユーザーをより簡単にするための追加の魔法を備えています。マージ時にGit、Hg、Bzrが行うこととは意味的に異なります。DAG(eagain.net/articles/git-for-computer-scientists)を気にしない限り、実際にはそれほど大きな違いはないと思います。
Damien Diederen、2010年

2
+100ボタンがないのは残念です。ありがとう。
チャーリーフラワー

私はあなたが話しているSVN 1.5機能がsvn:mergeinfoプロパティの使用であると思いますか?
MatrixFrog 2011年

@MatrixFrog:はい、これはまさに何をするかsvn:mergeinfoです。
sleske

12

Subversion(少なくともバージョン1.4以下)は何がマージされたかを追跡しないからです。Subversionの場合、マージは基本的にコミットと同じですが、Gitなどの他のバージョンコントロールでは、マージされたものが記憶されます。


7

Hgは、既に提供されている回答に影響されず、変更をマージするときにより多くの情報を使用するため(hginit.com)、優れたマージ機能を提供しました。

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

もちろん、最後にマージされたもの(ここで提供されるほとんどの回答で取り上げられている点)を思い出すことも、大きな勝利です。

ただし、Subversion 1.5以降では追加のマージ情報がSubversionプロパティの形式で保存されるため、どちらの改善点にも疑問があります。その情報が利用可能であり、Subversion MergeがHgまたはGitほどうまくマージを実装できなかった明確な理由はありません。確かにそうかどうかはわかりませんが、確かにsubversionの開発者がこの問題を回避しようとしているようです。


4

これは、Subversionがリビジョンの絶対的なタイムラインとともに中央サーバーのアイデアを持っているために、部分的にはそうかもしれないと思います。Mercurialは実際に配布されており、絶対的なタイムラインへのそのような言及はありません。これにより、Mercurialプロジェクトは機能の追加やサブプロジェクトごとのテストサイクルのためにブランチのより複雑な階層を形成できるようになりますが、チームは更新をヒットしてそれを実行することができないため、現在の状態を維持するために、マージをはるかに積極的に維持する必要があります。 。


3

Subversion(およびCVS)では、リポジトリが何よりも重要です。gitとmercurialでは、実際には同じようにリポジトリの概念はありません。ここでは、変更が中心的なテーマです。

私はあなたがどのように実装するかについてはあまり考えていませんでしたが、私の印象(苦い経験とたくさんの読書に基づく)は、この違いが非リポジトリベースのシステムでマージとブランチを非常に簡単にするものだということです。


1

私はSubversionの経験しかありませんが、TortoiseSVNのマージ画面は恐ろしく複雑であると言えます。幸いにも、それらにはドライランボタンが含まれているので、正しく実行しているかどうかを確認できます。複雑なのは、どこにマージしたいかという構成です。マージの設定を取得したら、マージは通常うまくいきます。次に、すべての競合を解決してから、マージされた作業コピーをリポジトリにコミットする必要があります。

Mercurialがマージの構成を簡単にできる場合、Subversionよりもマージが100%簡単になると言えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.