私の理解から、SVNは「分岐が簡単です。マージするのが難しい」。何故ですか?それらがマージする方法に違いはありますか?
Mercurial(およびGit)が問題なくマージされ、Subversionが偽の競合を提示する非常に具体的な状況については、 my Stack Overflow answer を参照してください。状況は、一部のファイルの名前を変更するブランチで行われる単純なリファクタリングです。
Tdammersの回答に関しては、そこには多くの誤解があります。
Subversion、Mercurial、およびGitはすべて、プロジェクトのリポジトリ全体のスナップショットを追跡します。それらをversions、revisions、またはchangesetsと呼んでも違いはありません。これらはすべて、一連のファイルの論理的にアトミックなスナップショットです。
マージのサイズに関しては、コミットのサイズ違いはありませんです。 3つのシステムすべてが標準の3者間マージアルゴリズムとマージし、そのアルゴリズムへの入力は次のとおりです。
重要ではない 2つのブランチバージョンがどのように作成されたか。祖先バージョン以降、1000個の小さなコミットを使用できます。または、1つのコミットを使用できます。重要なのは、ファイルの最終バージョンです。 (はい、これは驚くべきことです!はい、多くのDVCSガイドがこれをひどく間違っています。)
また、違いについていくつかの良い点を挙げています。
Subversionには「voodoo」があり、/trunk
から/branches/foo
などにマージできます。 MercurialとGitはこのモデルを使用しません。代わりにブランチが履歴で直接モデル化されます。したがって、履歴は線形ではなく、有向非循環グラフになります。これはSubversionで使用されているモデルよりもはるかに単純なモデルであり、これにより多くのコーナーケースが削減されます。
簡単にマージを遅延したり、他の人に処理させたりすることもできます。 hg merge
によって大量の競合が発生した場合は、同僚にhg pull
を依頼して、まったく同じ状態にすることができます。したがって、彼はhg merge
を行うことができ、おそらくあなたよりも競合を解決するのが得意です。
これは、更新が必要なSubversionでは非常に困難ですbeforeコミットできます。サーバー上の変更を単に無視して、独自の匿名ブランチでコミットし続けることはできません。一般に、Subversionはsvn update
を実行するときにdirty working copyをいじることを強制します。安全な場所に変更を保存していないので、これは一種の危険です。 GitとMercurialでは、最初にコミットしてから、必要に応じて更新およびマージできます。
GitとMercurialがSubversionよりもマージが優れている本当の理由は、実装の問題です。正しい答えが何であるかが明らかであっても、Subversionが処理できない名前の競合があります。 MercurialとGitはそれらを簡単に処理します。しかし、Subversionがこれらも処理できなかった理由はありません。一元化されていることは確かに理由ではありません。
中心的な問題は、これらのシステムがバージョン管理されたディレクトリ構造を表す方法にあります。
システム全体が展開するSubversionの基本的な概念は、version(または、svnの用語では「リビジョン」)の概念です。ある時点でのファイルのスナップショットです。履歴が完全に線形である限り、問題はありませんが、2つの独立した開発ラインからの変更をマージする必要がある場合、svnは両方の現在のバージョンを比較し、最後に共有されたバージョン間で3者間比較を行う必要がありますそして2つのヘッドバージョン。一方のヘッドで変更されているように見えても、もう一方のヘッドでは変更されない行は、簡単に解決できます。両方のヘッドでまったく同じように逸脱するラインはより困難ですが、通常は実行可能です。異なる方法で逸脱している行は、svnに「これを理解できない、人間、これを解決してください」と言わせます。
対照的に、gitとMercurialはバージョンではなくchangesetsを追跡します。リポジトリ全体はチェンジセットのツリーであり、それぞれが親に依存します。親のチェンジセットは任意の数の子を持つことができ、ツリーのルートは空のディレクトリを表します。言い換えると、git/hgは「最初は何もなかった、次にこのパッチが適用され、次にそのパッチなど」と言っています。 2行の開発をマージする必要がある場合、git/hgは各ヘッドが現在どのように見えるか、そして最後の一般的なバージョンがどのように見えるかを知るだけでなく、移行がどのように行われたかを知っているので、よりスマートなマージが可能になります。
DVCSでのマージを容易にするもう1つのことは、commitとPushの概念を分離し、任意の2つのクローン間であらゆる種類のクロスマージを許可する間接的な結果ですいつでも同じリポジトリ。コミットは他のすべてのチームメンバーに影響を与える中央リポジトリの更新でもあるため、svnでは、多くの場合、無関係な変更を伴う大きなチェンジセットをコミットする傾向があります。壊れたバージョンをコミットすると、誰もがあなたに腹を立てるでしょう。ほとんどの設定にはネットワーク化されたsvnサーバーが含まれるため、コミットにはネットワーク経由のデータのポンプも含まれます。つまり、コミットするとワークフローにかなりの遅延が生じます(特に作業コピーが古く、最初にプルする必要がある場合)。 gitとMercurialでは、コミットはローカルで行われ、どちらもローカルファイルシステムの処理に非常に効率的であるため、通常は即座に完了します。その結果、人々は(慣れれば)小さな増分変更をコミットし、それが機能するようになると、1ダース程度のプッシュを1回でコミットします。その後、マージ時間になると、SCMはより詳細な情報を入手できるため、競合を安全かつ自動的に解決するためのより適切な作業を実行できます。
そして、物事をさらに簡単にするニースの詳細があります: