ブランチが独立した開発ラインを維持するために使用される場合、ある段階で、一方のブランチで行われた変更をトランクに、またはその逆にマージしたいと思うでしょう。
Subversion でのブランチとマージの仕組みを理解することは、使い始める前に重要です。非常に複雑になる可能性があるためです。Subversion Book の ブランチとマージ の章を読むことを強くお勧めします。ここでは、その使用方法の詳細な説明と多くの例が示されています。
次に注意すべき点は、マージは常にワーキングコピー内で行われるということです。変更をブランチにマージしたい場合は、そのブランチのワーキングコピーをチェックアウトし、 → を使用してそのワーキングコピーからマージウィザードを起動する必要があります。
一般的に、マージを修正されていないワーキングコピーに対して実行することをお勧めします。WC に他の変更を加えた場合は、まずそれらをコミットしてください。マージが期待どおりに進まない場合は、変更を元に戻したい場合があります。元に戻すコマンドは、マージ前に行った変更を含め、すべての変更を破棄します。
以下に説明するように、わずかに異なる方法で処理されるマージには 3 つの一般的なユースケースがあります。マージウィザードの最初のページでは、必要な方法を選択するように求められます。
この方法は、ブランチ(またはトランク)に 1 つ以上のリビジョンを加えた場合に、それらの変更を別のブランチに移植したい場合に対応します。
Subversion に要求しているのは次のとおりです。「 ブランチ A のリビジョン 1 [から] ブランチ A のリビジョン 7 [まで] を取得するために必要な変更を計算し、それらの変更を(トランクまたはブランチ B の)ワーキングコピーに適用します。」
リビジョン範囲を空のままにすると、Subversion はマージ追跡機能を使用して、使用する正しいリビジョン範囲を計算します。これは、再統合または自動マージとして知られています。
これは、再統合方法のより一般的なケースです。Subversion に要求しているのは次のとおりです。「 トランクのヘッドリビジョン [から] ブランチのヘッドリビジョン [まで] を取得するために必要な変更を計算し、それらの変更を(トランクの)ワーキングコピーに適用します。」最終的な結果は、トランクがブランチとまったく同じになることです。
サーバー/リポジトリがマージ追跡をサポートしていない場合、これがブランチをトランクにマージバックする唯一の方法です。別のユースケースは、ベンダーブランチを使用している場合で、新しいベンダーからのドロップ後の変更をトランクコードにマージする必要がある場合に発生します。詳細については、Subversion Book の ベンダーブランチ の章をお読みください。
From: フィールドに、ワーキングコピーに移植する変更を含むブランチまたはタグの完全なフォルダ URL を入力します。 をクリックしてリポジトリを参照し、目的のブランチを見つけることもできます。以前にこのブランチからマージしたことがある場合は、以前に使用した URL の履歴を示すドロップダウンリストを使用するだけです。
名前変更または削除されたブランチからマージする場合は、そのブランチがまだ存在していたリビジョンに戻る必要があります。この場合、マージされるリビジョン範囲のペグリビジョンとしてそのリビジョンを指定する必要もあります(下記参照)。そうしないと、HEAD でそのパスが見つからない場合にマージが失敗します。
マージするリビジョン範囲フィールドに、マージするリビジョンのリストを入力します。これは、単一のリビジョン、コンマで区切られた特定のリビジョンのリスト、ダッシュで区切られたリビジョン範囲、またはこれらの任意の組み合わせにすることができます。
マージのペグリビジョンを指定する必要がある場合は、リビジョンの最後にペグリビジョンを追加します。例:5-7,10@3
。上記の例では、リビジョン 5、6、7、および 10 がマージされ、3 がペグリビジョンになります。
TortoiseSVN でリビジョン範囲を指定する方法と、コマンドラインクライアントで指定する方法には、重要な違いがあります。それを視覚化する最も簡単な方法は、柱と柵パネルのある柵を考えることです。
コマンドラインクライアントでは、マージする変更を 2 つの「柵柱」リビジョンを使用して指定します。これらは、前と後の時点を指定します。
TortoiseSVN では、マージする変更セットを「柵パネル」を使用して指定します。この理由が明確になるのは、ログダイアログを使用してマージするリビジョンを指定する場合です。各リビジョンは変更セットとして表示されます。
リビジョンをチャンクでマージする場合、Subversion Book に示されている方法では、今回は 100〜200 をマージし、次回は 200〜300 をマージすることになります。TortoiseSVN では、今回は 100〜200 をマージし、次回は 201〜300 をマージします。
この違いは、メーリングリストで多くの議論を呼びました。コマンドラインクライアントとの違いがあることは認識していますが、GUI ユーザーの大多数にとって、実装した方法の方が理解しやすいと信じています。
必要なリビジョン範囲を選択する最も簡単な方法は、Shift キー修飾子を使用して)その範囲を選択します。 をクリックすると、マージするリビジョン番号のリストが自動的に入力されます。
をクリックすることです。これにより、最近の変更がログコメントとともにリスト表示されます。単一のリビジョンからの変更をマージする場合は、そのリビジョンを選択するだけです。複数のリビジョンからの変更をマージする場合は、(通常のワーキングコピーから変更を戻す場合、すでにコミットされている変更を元に戻すには、元に戻すリビジョンを選択し、リバースマージボックスがチェックされていることを確認してください。
すでにこのブランチからいくつかの変更をマージしている場合は、変更をコミットしたときのログメッセージに最後にマージしたリビジョンをメモしておくとよいでしょう。その場合は、ワーキングコピーの
を使用して、そのログメッセージを追跡できます。リビジョンを変更セットとして考えていることを覚えておいてください。このマージの開始点として、最後のマージの終了点後のリビジョンを使用する必要があります。たとえば、前回リビジョン 37 から 39 をマージした場合、今回のマージの開始点はリビジョン 40 にする必要があります。Subversion のマージ追跡機能を使用している場合は、すでにマージされたリビジョンを覚えておく必要はありません。Subversion がそれを記録してくれます。リビジョン範囲を空白のままにすると、まだマージされていないすべてのリビジョンが含まれます。詳細については、「マージ追跡」のセクションをお読みください。
マージ追跡を使用すると、ログダイアログには、以前にマージされたリビジョンと、共通の祖先ポイントより前のリビジョン、つまりブランチがコピーされる前のリビジョンがグレー表示されます。マージできないリビジョンを非表示チェックボックスを使用すると、これらのリビジョンを完全にフィルタリングして、マージできるリビジョンのみを表示できます。
他の人が変更をコミットしている可能性がある場合は、HEAD リビジョンの使用には注意してください。他の人が最後の更新後にコミットした場合、それがあなたが考えているリビジョンを指していない可能性があります。
リビジョン範囲を空のままにするか、すべてのリビジョンラジオボタンをオンにすると、Subversion はまだマージされていないすべてのリビジョンをマージします。これは、再統合または自動マージとして知られています。
再統合マージにはいくつかの条件が適用されます。まず、サーバーがマージ追跡をサポートしている必要があります。ワーキングコピーは無限深度(スパースチェックアウトなし)である必要があり、ローカルで変更されたアイテム、切り替えられたアイテム、または HEAD 以外のリビジョンに更新されたアイテムがあってはなりません。ブランチ開発中にトランクに加えられたすべての変更は、ブランチにマージされている(またはマージ済みとしてマークされている)必要があります。マージするリビジョン範囲は自動的に計算されます。
「マージオプション」のセクションに進みます。
をクリックして、
この方法を使用してフィーチャーブランチをトランクにマージバックする場合は、トランクのワーキングコピー内からマージウィザードを開始する必要があります。
From: フィールドに、トランクの完全なフォルダ URL を入力します。これは間違っているように聞こえるかもしれませんが、トランクはブランチの変更を追加する開始点であることを覚えておいてください。 をクリックしてリポジトリを参照することもできます。
To: フィールドに、フィーチャーブランチの完全なフォルダ URL を入力します。
From リビジョンフィールドと To リビジョンフィールドの両方に、2 つのツリーが同期された最後のリビジョン番号を入力します。誰もコミットしていないことが確実な場合は、両方の場合で HEAD リビジョンを使用できます。その同期以降に他の人がコミットした可能性がある場合は、より新しいコミットを失うことを避けるために、特定のリビジョン番号を使用してください。
を使用してリビジョンを選択することもできます。
ウィザードのこのページでは、マージプロセスを開始する前に、高度なオプションを指定できます。ほとんどの場合、デフォルト設定を使用するだけで十分です。
マージに使用する深さを指定できます。つまり、ワーキングコピーのどこまでマージを実行するかを指定できます。使用される深さの用語については、「チェックアウト深度」のセクションで説明されています。デフォルトの深さは ワーキングコピーです。これは既存の深さ設定を使用し、ほとんどの場合、必要なものです。
ほとんどの場合、マージではファイルの履歴を考慮し、共通の祖先からの相対的な変更がマージされるようにする必要があります。場合によっては、関連している可能性はあるものの、リポジトリにはないファイルをマージする必要がある場合があります。たとえば、サードパーティライブラリのバージョン 1 と 2 を 2 つの異なるディレクトリにインポートしたとします。それらは論理的に関連していますが、Subversion はインポートした tarball しか認識しないため、これについて何も知りません。これらの 2 つのツリー間の差分をマージしようとすると、完全な削除の後に完全な追加が表示されます。Subversion に履歴ベースの差分ではなくパスベースの差分のみを使用させるには、祖先を無視ボックスをチェックします。このトピックの詳細については、Subversion Book の 祖先の認識または無視 をお読みください。
行末と空白の変更の処理方法を指定できます。これらのオプションについては、「行末と空白のオプション」のセクションで説明されています。デフォルトの動作では、すべての空白と行末の差分をマージされる実際の違いとして扱います。
マージを強制とマークされたチェックボックスは、ローカルで変更されたファイルまたはバージョン管理されていないファイルに影響を与える着信削除によるツリーコンフリクトを回避するために使用されます。ファイルが削除されると、それを回復する方法はありません。そのため、デフォルトではこのオプションはチェックされていません。
混合リビジョンを許可(非推奨)とマークされたチェックボックスは、混合リビジョンワーキングコピーへのマージを許可するために使用されます(コマンドラインオプション --allow-mixed-revisions
に対応)。Subversion 1.7 以降のデフォルトでは、混合リビジョンワーキングコピーへのマージは許可されていません。その理由は、Subversion Book の ブランチの同期維持 のセクションの終わりに説明されています。混合リビジョンワーキングコピーへのマージの考えられる問題を理解している場合は、このチェックボックスをオンにして、とにかくマージを実行できます。
マージ追跡を使用しており、実際にはここでマージを実行せずに、リビジョンをマージ済みとしてマークしたい場合は、マージのみを記録チェックボックスをオンにします。これを行う理由は 2 つ考えられます。マージがマージアルゴリズムには複雑すぎるため、変更を手動でコーディングし、マージ追跡アルゴリズムがそれを認識できるように変更をマージ済みとしてマークする場合があります。または、特定のリビジョンがマージされないようにする場合もあります。すでにマージ済みとしてマークすると、マージ追跡対応クライアントでのマージの発生を防ぐことができます。
これで、すべて設定されました。あとは、まったく変更されません。実際のマージによって変更されるファイルのリストと、コンフリクトが発生する可能性のあるファイルが表示されます。マージ追跡によりマージプロセスが大幅に複雑になるため、テストマージでコンフリクトとしてマークされたファイルが実際には問題なくマージされる可能性があるため、コンフリクトなしでマージが完了するかどうかを事前に確認する方法は保証されていません。
ボタンをクリックするだけです。結果をプレビューしたい場合は、 をクリックすると、マージ操作がシミュレートされますが、ワーキングコピーはマージ進行状況ダイアログには、マージの各段階が、関連するリビジョン範囲とともに表示されます。これは、予想よりも 1 つ多くのリビジョンを示す場合があります。たとえば、リビジョン 123 をマージするように要求した場合、進行状況ダイアログには「 リビジョン 122 から 123 をマージ中 」と表示されます。これを理解するには、マージが Diff と密接に関連していることを覚えておく必要があります。マージプロセスは、リポジトリ内の 2 つのポイント間の差分リストを生成し、それらの差分をワーキングコピーに適用することによって機能します。進行状況ダイアログは、Diff の開始点と終了点を単に示しているだけです。
これでマージは完了しました。マージを見て、期待どおりになっているかどうかを確認することをお勧めします。マージは通常、非常に複雑です。ブランチがトランクから大きく乖離している場合、コンフリクトが頻繁に発生します。
リビジョンがワーキングコピーにマージされるたびに、TortoiseSVN はマージされたすべてのリビジョンからログメッセージを生成します。これらは、コミットダイアログの
ボタンから利用できます。生成されたメッセージをカスタマイズするには、ワーキングコピーで対応するプロジェクトプロパティを設定します。「マージログメッセージテンプレート」のセクションを参照してください。
1.5 より前の Subversion クライアントおよびサーバーの場合、マージ情報は保存されず、マージされたリビジョンは手動で追跡する必要があります。変更をテストし、このリビジョンをコミットするときは、コミットログメッセージに、マージで移植されたリビジョン番号を常に含める必要があります。後で別のマージを適用する場合は、すでにマージしたものを知っておく必要があります。変更を複数回移植したくないためです。これに関する詳細については、Subversion Book の マージのベストプラクティス を参照してください。
サーバーとすべてのクライアントが Subversion 1.5 以降を実行している場合、マージ追跡機能はマージされたリビジョンを記録し、リビジョンが複数回マージされるのを防ぎます。これにより、毎回リビジョン範囲全体をマージするだけで、新しいリビジョンのみが実際にマージされることがわかるため、生活がはるかに楽になります。
ブランチ管理は重要です。このブランチをトランクと常に最新の状態に保ちたい場合は、ブランチとトランクが大きく乖離しないように、頻繁にマージするようにしてください。もちろん、上記で説明したように、変更の繰り返しマージは避ける必要があります。
フィーチャーブランチをトランクにマージバックしたばかりの場合、トランクにはすべての新しいフィーチャーコードが含まれるようになり、ブランチは不要になります。必要に応じて、リポジトリから削除できます。
Subversion は、ファイルとフォルダ、およびその逆(フォルダからフォルダ、ファイルからファイルのみ)をマージできません。ファイルをクリックしてマージダイアログを開くと、そのダイアログでファイルへのパスを指定する必要があります。フォルダを選択してダイアログを表示する場合は、マージするフォルダ URL を指定する必要があります。
Subversion 1.5 では、マージ追跡の機能が導入されました。あるツリーから別のツリーに変更をマージすると、マージされたリビジョン番号が保存され、この情報はいくつかの異なる目的で使用できます。
同じリビジョンを 2 回マージする危険性(繰り返しマージの問題)を回避できます。リビジョンがマージ済みとしてマークされると、そのリビジョンを範囲に含む今後のマージでは、そのリビジョンはスキップされます。
ブランチをトランクにマージバックすると、ログダイアログにブランチコミットがトランクログの一部として表示され、変更のトレーサビリティが向上します。
マージダイアログ内からログダイアログを表示すると、すでにマージされたリビジョンはグレーで表示されます。
ファイルの blame 情報を表示するときに、マージを実行した人ではなく、マージされたリビジョンの元の作成者を表示するように選択できます。
実際にはマージを実行せずに、マージされたリビジョンのリストに含めることで、リビジョンをマージしないとしてマークできます。
マージ追跡情報は、クライアントがマージを実行するときに svn:mergeinfo
プロパティに保存されます。マージがコミットされると、サーバーはその情報をデータベースに保存し、マージ、ログ、または blame 情報を要求すると、サーバーは適切に応答できます。システムが正しく機能するためには、サーバー、リポジトリ、およびすべてのクライアントがアップグレードされていることを確認する必要があります。以前のクライアントは svn:mergeinfo
プロパティを保存せず、以前のサーバーは新しいクライアントから要求された情報を提供しません。
マージ追跡の詳細については、Subversion の マージ追跡ドキュメント を参照してください。
コンフリクトリゾルバーダイアログのテキストは SVN ライブラリによって提供されているため、TortoiseSVN ダイアログのように(まだ)翻訳されていない可能性があります。申し訳ありません。
マージは常にスムーズに進むとは限りません。コンフリクトが発生する場合があります。TortoiseSVN は、マージコンフリクトダイアログを表示することで、このプロセスを支援します。
変更の一部はスムーズにマージされ、他のローカルの変更はすでにリポジトリにコミットされている変更とコンフリクトしている可能性があります。マージできるすべての変更はマージされます。マージコンフリクトダイアログでは、コンフリクトしている行を処理するさまざまな方法が提供されます。
ファイルの内容またはそのプロパティの変更が原因で発生する通常のコンフリクトの場合、ダイアログには、コンフリクトしている部分のどれを保持または拒否するかを選択できるボタンが表示されます。
コンフリクトを今すぐ処理しないでください。マージを続行し、マージが完了してからコンフリクトを解決します。
ファイルは、マージからの変更も、ワーキングコピーで行った変更もなしで、元の状態のままになります。
ローカルの変更をすべて破棄し、マージソースから到着したファイルを使用します。
マージソースからの変更をすべて破棄し、ローカル編集したファイルを残します。
ローカルの変更のうち、マージソースからの変更とコンフリクトしている部分を破棄します。ただし、コンフリクトしていないローカルの変更はすべて残します。
ローカルの変更とコンフリクトしているマージソースからの変更を破棄します。ただし、ローカルの変更とコンフリクトしていないすべての変更は保持します。
コンフリクトを解決済みとしてマークします。このボタンは、
ボタンを使用してコンフリクトを手動で編集し、それらの変更をファイルに保存するまで無効になっています。変更が保存されると、ボタンが有効になります。マージエディターを起動して、コンフリクトを手動で解決できるようにします。ファイルが保存されるように、ファイルを保存することを忘れないでください。
ボタンが有効になります。
ツリーコンフリクトがある場合は、まずツリーコンフリクトのさまざまなタイプとその発生理由について、「ツリーコンフリクト」のセクションを参照してください。
マージ後のツリーコンフリクトを解決するために、コンフリクトを解決する方法に関するさまざまなオプションを示すダイアログが表示されます。
さまざまなツリーコンフリクトの状況が考えられるため、ダイアログには、特定のコンフリクトに応じて、それらを解決するためのボタンが表示されます。ボタンのテキストとラベルは、コンフリクトを解決するためのオプションが何をするかを説明しています。不明な場合は、ダイアログをキャンセルするか、 ボタンを使用して後でコンフリクトを解決してください。
別のブランチで新しい機能を開発する場合、機能が完了したときの再統合の方針を立てておくことをお勧めします。trunk
で他の作業が同時に進行している場合、時間の経過とともに差が大きくなり、マージバックが悪夢になる可能性があります。
機能が比較的単純で、開発に時間がかからない場合は、単純なアプローチを採用できます。それは、機能が完了するまでブランチを完全に分離しておき、ブランチの変更をトランクにマージバックすることです。マージウィザードでは、これは単純な リビジョン範囲をマージとなり、リビジョン範囲はブランチのリビジョンスパンになります。
機能に時間がかかり、trunk
の変更を考慮する必要がある場合は、ブランチを同期させておく必要があります。これは単に、定期的にトランクの変更をブランチにマージすることを意味します。これにより、ブランチにはトランクのすべての変更とプラス新しい機能が含まれます。同期プロセスでは、リビジョン範囲をマージを使用します。機能が完了したら、ブランチを再統合または 2 つの異なるツリーをマージを使用して trunk
にマージバックできます。
トランクからフィーチャーブランチへのすべての変更をマージする別の(高速な)方法は、拡張コンテキストメニューから Shift キーを押しながらファイルを右クリックします)。
→ を使用することです(
このダイアログは非常に簡単です。行う必要があるのは、「マージオプション」のセクションで説明されているように、マージのオプションを設定することだけです。残りは TortoiseSVN によってマージ追跡を使用して自動的に行われます。