重複の可能性:
私はSubversionオタクです。なぜMercurialやGit、その他のDVCSを検討する必要があるのですか?
分散バージョン管理(Git、HG)は、SVNでのマージが困難で苦痛であるため、本質的に集中型バージョン管理(SVNなど)よりも優れていると誰かが言っているのを時々耳にします。問題は、SVNでのマージに問題がなかったことです。実際のSVNユーザーではなく、DVCSの支持者によって行われたという主張しか聞いていないので、私は これらの不快なコマーシャルを思い出しがちですテレビで 彼らはあなたがすでに持っているものをうまく動かしているものを使うのが信じられないほど難しいとごまかしの俳優にふりをさせることによってあなたが必要としない何かをあなたに売り込もうとします。
そして、常に持ち出されるユースケースは、ブランチを再マージすることであり、これは再びそれらのストローマン製品の広告を思い出させます。自分が何をしているのかわかっている場合は、最初にブランチを再マージするべきではありません(その必要もありません)。 (もちろん、根本的に間違っていてばかげていることをしているときは、難しいことです!)
では、とんでもないストローマンのユースケースを無視して、DVCSシステムでのマージよりも本質的に難しいSVNマージには何があるのでしょうか。
これは、svnが2つのブランチの最新の共通祖先を正確に決定するための適切なデータ構造を欠いていたためです。これは1回だけマージされるブランチでは大した問題ではありませんが、複数のブランチが複数回マージされる状況では、多くの誤ったマージ競合を引き起こす可能性があります。
私はsvnを厳密にはフォローしていませんが、これらの特定の技術的な問題は最近のバージョンで修正されていると理解しています。しかし、それは神話を払拭するのに十分早い段階では修正されておらず、マージのためにDVCSを試した人々は他の理由でそれに固執しました。
自分が何をしているのかわかっている場合は、最初にブランチを再マージするべきではありません(その必要もありません)。 (もちろん、根本的に間違っていてばかげていることをしているときは、難しいことです!)
そしてそこには、あなたの混乱の源と一般的な問題全体があります。
あなたはブランチをマージすることは「基本的に間違っていてばかげている」と言います。まあ、それはまさに問題です:あなたはブランチをマージすべきではないものとして考えています。どうして?あなたはブランチのマージがhardであることを知っているSVNユーザーだからです。したがって、あなたは決してそれをせず、他人にそれをしないように勧めます。マージを回避するためにトレーニングされています。 マージを回避するために使用するテクニックを開発しました。
私はMercurialユーザーです。私が唯一の開発者である私自身のプロジェクトでさえ、私はブランチを常にマージします。私は修正を入れたリリースブランチを持っています。まあ、私はそれをメインラインにマージして、修正がそこに行くようにします。
SVNを使用している場合、コードベースの完全に異なる構造を採用します。どうして? SVNはマージを困難にするため、複雑なマージをavoidするイディオムとテクニックを開発するためです。
DVCSはデフォルトの状態であるため、複雑なマージを容易にします。 DVCSでは、すべてが多かれ少なかれ分岐です。そのため、それらの全体的な構造は、マージを容易にするためにゼロから構築されています。これにより、マージを決して使用しないSVNワークフローではなく、日常的にマージを使用するワークフローを開発できます。
単純な事実はこれです。SVNとは異なる方法でDVCSにアプローチする必要があります。これらの非常に異なる種類のバージョン管理システムには、適切なイディオムを使用する必要があります。 SVNでは、マージが難しいため、マージを伴わないイディオムを採用します。 DVCSでは、大したことではないのでマージを頻繁に使用するイディオムを採用します。
適切な仕事のための適切なツール。
問題は、マージに焦点を当てたワークフローは、マージしないSVNスタイルのワークフローよりもlot使いやすく、使いやすいことです。 releaseブランチから何かがdevブランチに取り込まれたときを確認するのは簡単です。ブランチ間のさまざまな相互作用を簡単に確認できます。物事のテストブランチを作成し、テストが機能しない場合は簡単に切り離すことができます。等々。
本当に、 ジョエルは私がこれよりもずっとよく説明しています 。よく読んでください。
他のほとんどの回答で私が見るのは、しばらくSVNを使用していない人からのものであるようです。誰かが正確に述べているように、「それは神話を払拭するのに十分早い時期に修正されなかった」。
最近継承したレガシープロジェクトでSVN 1.6から1.8を使用した現在の経験から、SVNはマージをはるかに簡単にするために長い道のりを歩んできました。ただし、これは絶対に確実なことではありません。また、 think は、ユーザーが意図した用途から逸脱することで簡単に苦しむことはありません。
私はSVNをよく知っていて、それまでの間、Mercurialを個人的なプロジェクトで試しましたが、このプロジェクトの前にSVNで多くのブランチを作成したことはありませんでした。かなりの試行錯誤があり、開始時に予期しないマージ競合が lot 発生しました。
しかし、結局のところ、1つ(またはその他の問題)が発生するたびに、適切にを実行しなかったことが原因であることに気付きました(別名 "SVNの方法"-間違いなく、適切なバージョン管理方法)。私はこれが難しいところだと思います:組織化されていない方法でやりたいことは何もできず、SVNが完全に機能することを期待します。マージは、ユーザーが真の力を発揮する前に、ユーザーからの厳しい規律を必要とします。
マージをクリーンに使用するための要件ではないにせよ、私が気づいたのは次の点です。
上記に従わない場合、競合が発生する可能性が非常に高くなります。それらは常に解決可能ですが、時間を費やすのはそれほど楽しいものではありません。
ああ、マージについてもう1つあります。私が読んで試したすべてのことから、SVNは本当にやっかいです:削除/移動/名前を変更したファイル/フォルダー。 どうやら、SVNはまだ1つのブランチで名前変更、削除、または移動されているファイルを処理できず、元のバージョンが別のブランチで変更されてから、それらをマージします。ファイルがどこに移動したのかわからないだけで、反対に変更を「忘れて」しまいます。 1つの変更は明らかに解決できません(ファイルを削除または変更しますが、両方を行うことはできません)が、移動/名前変更されたファイルに変更を適用すると、 should は機能しますが、機能しません。うまくいけば、これはすぐに修正されます。
それで、全体として、SVNマージは簡単ですか?私はそうは思いません。もちろん、のんきなやり方ではありません。 bad ?私はそうは思いません。それはあなたがそれを間違った方法で使用し、あなたが何をしているかについて十分に考えていないときにのみ、あなたの顔に吐き出されます。
これに基づいて、私の経験からこれらのことについて少し寛容であり、すべてが最初から自動化されていた(少なくとも最初のバージョンから)ため、人々がMercurialを好む理由がわかります(たとえば)。しかし、SVNはかなり追いついてきたので、もうそれほどバッシングする価値はありません。
内部データモデルは根本的に異なります。
基本的に、SVNでは、ブランチの履歴を見ると、そのブランチで何が起こったかしかわかりません。したがって、ブランチB
からブランチA
にマージすると、ブランチA
の履歴には、B
に対して明示的に行われたすべての変更を含む1つの大きなコミットが含まれます。分岐しました。
SVNの最初のバージョンでは、ブランチB
をブランチA
にもう一度マージする必要がある場合、マージするブランチB
のリビジョン範囲を手動で指定する必要がありました同じリビジョンを2回マージすることを避けるため。賢い開発者はもちろん、「M:1でマージされたB:1234」のようなコミットメッセージを使用します。
SVN 1.5はこれを「修正」しました。しかし、マージが基本的に適用される方法は変わりませんでした。ブランチA
に追加のメタデータを追加するだけで、リビジョン1234がマージされたことをSVNに知らせ、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を使用したとき、あるブランチでファイルの名前が変更され、別のブランチで変更されたマージを処理できませんでした。
私はSVNマージのかなりの部分を実行しました-長期にわたる開発ブランチとリリースブランチを含む。概して、私は生き残った。マージは常にトリッキーですが、DCVSの場合、マイナス面はひどく悪いことではありません。すべてローカルであるため、既知の適切なリビジョンに更新して続行してください。一方、SVNではサーバー側で多くのことが発生したため、リカバリは醜いものでした。通常、ローカルコピーを消去してから、新しいクリーンブランチをチェックアウトして再試行しました。私の場合は悪くありませんでした-SVNボックスへのギガビット接続が役立ちます。しかし、低速の接続を使用しているため、マージを含めてすべてが永遠にかかるため、これに多くの問題を抱えている請負業者がいました。