分散型 VCS (git、mercurial など) の多くは、Subversion などの従来の VCS よりもマージが優れていると聞いています。これは何を意味するのでしょうか?合併をより良くするために、彼らはどのようなことをしていますか? これらのことは、従来の VCS で実行できますか?
おまけの質問: SVN 1.5 のマージ トラッキングは、競技場を平準化しますか?
分散型 VCS (git、mercurial など) の多くは、Subversion などの従来の VCS よりもマージが優れていると聞いています。これは何を意味するのでしょうか?合併をより良くするために、彼らはどのようなことをしていますか? これらのことは、従来の VCS で実行できますか?
おまけの質問: SVN 1.5 のマージ トラッキングは、競技場を平準化しますか?
SVN のマージ機能は適切であり、単純なマージ シナリオは正常に機能します。たとえば、トランクが RB でのコミットを追跡するブランチとトランクをリリースします。
より複雑なシナリオは、急速に複雑になります。たとえば、安定したブランチ ( stable
) とtrunk
.
stable
あなたは新しい機能のデモを行いたいと考えており、よりも安定しているため、それをベースにしtrunk
たいと考えています。オン。trunk
stable
trunk
ブランチを作成するdemo
と、マージ グラフは次のようになります。
stable -> demo -> trunk
(あなた)stable -> trunk
(他の開発者)しかし、 からの変更をにマージstable
しdemo
、次に にマージdemo
するとどうなるでしょうか。trunk
その間、常に他の開発者も にマージstable
していtrunk
ます。stable
SVN は、に 2 回マージされるため、マージと混同されtrunk
ます。
これを回避する方法はありますが、git/Bazaar/Mercurial では、これは単純に起こりません。マージ パス全体で各コミットを識別するため、コミットが既にマージされているかどうかを認識します。
ほとんどの答えはSubversionに関するもののようです。したがって、ここにGit(およびその他のDVCS)に関するものがあります。
分散バージョン管理システムでは、あるブランチを別のブランチにマージするときに、新しいマージコミットを作成します。これは、マージを解決した方法を記憶し、マージのすべての親を記憶します。この情報は、バージョン1.5より前のSubversionには単に欠けていました。これには、SVKやsvnmergeなどの追加ツールを使用する必要がありました。この情報は、マージを繰り返す場合に非常に重要です。
この情報のおかげで、分散バージョン管理システム(DVCS)は、任意の2つのブランチの共通の祖先(または共通の祖先)(マージベースとも呼ばれます)を自動的に見つけることができます。以下のリビジョンのASCIIアート図を見てください(それがあまりにもひどく壊されていないことを願っています)、
--- O --- * --- * ---- M --- * --- * --- 1 \ / \ --- * --- A /-*----2
ブランチ「2」をブランチ「1」にマージする場合、マージを生成するために使用する共通の祖先は、「A」とマークされたバージョン(コミット)になります。ただし、バージョン管理システムがマージの親に関する情報を記録しなかった場合(「M」は同じブランチの以前のマージです)、コミット「A」であることが検出できず、コミット「O」が検出されます。代わりに共通の祖先(マージベース)として...すでに含まれている変更を繰り返し、大きなマージの競合が発生します。
分散バージョン管理システムはそれを正しく行う必要がありました。つまり、他の誰かにコードを取得させる方法があるため、最初からマージを非常に簡単にする必要がありました(マージの親にマーク/タグを付けたり、手動でマージ情報を提供したりする必要はありません)。プロジェクトへの参加は、彼/彼女にコミットアクセスを与えることではなく、彼/彼女のリポジトリからプルすることでした。他のリポジトリからコミットを取得し、マージを実行します。
マージに関する情報はSubversion1.5にあります。Subversion1.5リリースノート。注意事項:ブランチをトランクにマージするのと、トランクをブランチにマージするのとでは、異なる(!)オプションが必要です。すべてのブランチが等しいわけではありません(分散バージョン管理システムでは、[通常]技術的に同等です)。
1.5 のマージ トラッキングは、マージ トラッキングがないよりはましですが、依然として手動プロセスがほとんどです。マージされているリビジョンとマージされていないリビジョンを記録する方法は気に入っていますが、完璧に近いとは言えません。
Merge は 1.5 で素敵なダイアログを持っています。マージするリビジョンを個別に選択することも、ブランチ全体を選択することもできます。次に、ローカルで発生する(そして永遠にかかる)マージをトリガーします。その後、一連のファイルを読み取ることができます。各ファイルが正しい動作をするかどうかを論理的にチェックする必要があり (できれば、ファイルの単体テストを実行することをお勧めします)、競合がある場合はそれらを解決する必要があります。満足したら、変更をコミットすると、その時点でブランチはマージされたと見なされます。
少しずつ行うと、SVN は以前にマージしたことを覚えているため、マージが可能になります。いくつかのマージのプロセスと結果は、控えめに言っても奇妙であることがわかりました...
これらのバージョン管理システムは、より多くの情報を持っているため、より適切に機能します。
1.5 より前の SVN は、最新世代より前のほとんどの VCS と同様に、2 つのコミットをどこかにマージしたことを実際には覚えていません。2 つの分岐は、最初に分岐したときに共通の祖先を共有していることを覚えていますが、共通の基盤として使用できる最近のマージについては知りません。
私は SVN post 1.5 について何も知らないので、おそらく彼らはこれを改善したのでしょう。
軽薄な答え: 一部のプログラミング言語が他の言語よりもテキスト/数学に優れているのはなぜですか?
本当の答え:そうしなければならないからです。分散型 VCS は、マージがサードパーティによって行われているため、競合するコードの作成者のどちらも手動でマージを微調整できない時点でマージの多くを行います。その結果、ほとんどの場合、マージ ツールは正しく処理する必要があります。
SVN との契約では、一方または他方を書いていないものをマージすることになった場合、何かファンキーな (そして間違った?) ことを行っていることになります。
IIRC のほとんどの VCS は、使用するように要求されたものにマージをシェルアウトできるため、(理論的には) SVN が GIT/mercurial マージ エンジンを使用することを妨げるものは何もありません。YMMV