内部データモデルは根本的に異なります。
基本的に、SVNでは、ブランチの履歴を見ると、そのブランチで何が起こったのかしかわかりません。そのB
ため、ブランチからブランチにマージすると、ブランチA
の履歴には、ブランチ以降にA
明示的に行われたすべての変更を含む1つの大きなコミットが含まれますB
。
SVNの最初のバージョンでは、B
ブランチをA
もう一度ブランチにマージする必要があるB
場合、同じリビジョンを2回マージしないように、マージするブランチのリビジョン範囲を手動で指定する必要がありました。賢い開発者はもちろん、「M:Merged in B:1234」のようなコミットメッセージを使用します。
SVN 1.5はこれを「修正」しました。しかし、マージの基本的な適用方法は変わりませんでした。単に追加のメタデータをbranchに追加してA
、SVNにリビジョン1234がマージされたことを知らせるだけで、SVNが正しいリビジョン範囲を自動的に選択できるようになりました。
ただし、このソリューションは、基本的に、マージされたものの追跡を基本的にサポートしないデータモデルの回避策です。
2つのブランチをマージするのは比較的簡単な例です。しかし、このより複雑なシナリオのイメージング
A
からブランチを作成しtrunk
、ここでいくつかのコミットを行います
- ここ
B
からブランチを作成しA
、ここでいくつかのコミットを行います
- でいくつかのコミットを
trunk
行い、A
- に
B
統合trunk
- に
A
統合B
- に
A
統合trunk
- マージ
B
にtrunk
(これは実際には何もやるべきではありません)
メタデータモデルを使用してこれを正しく処理することは非常に複雑になります(SVNが実際にこのシナリオを正しく処理するかどうかはわかりませんし、テストする気もありません)。
gitでこのシナリオを処理するのは非常に簡単です。
gitでは、コミットするたびに、そのコミットを表す内部オブジェクトには前のヘッドへの参照が含まれます。ブランチにマージすると、コミットにはマージされるすべてのブランチの前のヘッドへの参照が含まれます(gitでは一度に複数のブランチをマージできます)
したがって、gitで1つのコミットの履歴を調べると、すべての履歴、ブランチがいつ、マージされたか、ブランチとマージの間の両方のブランチの履歴を見ることができます。
したがって、部分的にマージされたブランチをマージする場合、すでにマージされているものとされていないものを判別するのは非常に簡単です。
Mercurialの経験はありませんが、内部の動作はgitに似ていると思われます。
基本的に、SVNにとっては、分岐を安価にすることが設計目標でした。しかし、gitでは、マージを安価にすることが設計目標でした。
最後に、最後にSVNを使用したとき、マージを処理できませんでした。1つのブランチでファイル名が変更され、別のブランチで変更されました。