Subversion (および CVS) では、リポジトリが何よりも重要です。git と mercurial では、同じようにリポジトリの概念はありません。ここでは変化が中心的なテーマです。
+1
CVS/SVN の問題点は、これらのシステム
が変更の親子関係を記憶していないことにあります。Git と Mercurial では、コミットは複数の子を持つことができるだけでなく、複数の親を持つこともできます!
gitk
これは、グラフィカル ツールの 1 つまたはを使用して簡単に確認できますhg
view
。次の例では、ブランチ #2 はコミット A で #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 以降のマージ記録機能の経験はありませんが、ワークフローは分散システムよりもはるかに工夫されているようです。もしそうなら、それはおそらく、上記のコメントで述べたように、変更自体よりもリポジトリの編成に焦点が置かれているためです。