ここでの問題はワークフローです。ブランチは、あなたが使用している方法で使用するようには設計されていません。ブランチのソース (この例では/trunk
) からブランチに変更をマージできますが、ブランチの変更をソースにマージしたら、ブランチの使用を停止して削除する必要があります。(補足: 技術的には、ブランチを再統合した後にブランチを存続させる「公式の」方法がありますが、ブランチを削除して再作成するのと同等であり、実行するのがより難しいため、通常は最善の方法ではありません)
ここでの問題はメタデータです。ブランチ間で変更をマージすると、Subversion はどのリビジョンがマージされたかを示すメタデータを記録します。ブランチからトランクにマージすると、ブランチからの特定のリビジョンがマージされたことを示すメタデータがトランクに添付されます。次にトランクからの変更をマージするとき->マージされるリビジョンの 1 つは、ブランチ -> トランク マージを表すトランク リビジョンです。この時点で、メタデータはかなり紛らわしく、ほぼ循環的であり、最後のマージ以降にブランチで変更した古いコードをマージすることで、実際にブランチを破損する可能性があります。マージが正常に終了した場合でも、将来のマージで競合が発生する可能性が高くなります。一般に、これは非常にエラーが発生しやすく、Subversion が設計されたユース ケースではありません。
一般に、ブランチは一時的で短期間の開発作業用に設計されています。あなたがしていることは、ブランチというよりも長期的なフォークのように聞こえますが、それは間違いなく Subversion の典型的な使用例の 1 つではありません。ここにはいくつかのオプションがあります。
1) ブランチからトランクにマージするときは、マージに関するメタデータを記録しないでください。(Subversion に任せるのではなく) 手動で変更をマージするか、変更をマージしてからコミットする前にメタデータの変更を元に戻します。これはあまり良い解決策ではなく、コピー/貼り付けエラーが発生する可能性がありますが、問題が少なくなる可能性があります。あなたはまだ標準の Subversion ワークフローの外で操作しているため、まだ問題が発生することが予想されます。
2) ブランチを部分的にトランクにマージすることは避けてください。ブランチのすべての変更をマージする場合は、--reintegrate
マージを実行してからブランチを削除します (同じ名前のブランチであっても、いつでも新しいブランチを作成できます)。変更のサブセットのみをマージする必要がある場合は、(ブランチではなく) トランクで初期開発を行い、トランクからブランチへの変更をマージします。そうすれば、すべてのマージは引き続き同じ方向に進み、最終的にトランクとブランチの両方に変更が反映されます。
3) gitの使用を検討してください。あなたが説明しているワークフローは、git を使用するとより簡単に実行でき、実行するために多くのフープをジャンプする必要はありません。Subversion 上で git を実行することもできるため、Subversion リポジトリからプルして変更をプッシュするローカル マシン上の git リポジトリを使用できます。
4) 別のブランチが不要になるようにコードをリファクタリングして、フォークの必要性を排除します。共通の機能を共有モジュールに分割し、共通のインターフェイスの背後にある相違点を隠します。必要に応じて、コンパイル時のフラグを使用して、ビルドするバージョンを選択できます。これにより、マージを完全に行う必要がなくなります。
#4は明らかに最良の解決策です。特にコードベースが大きく、ブランチが主要なアーキテクチャの変更を行う場合、そのようなことをすべての場合に行うことができない場合があることを理解しています. それが不可能な場合は、オプション #3 をお勧めします。私は個人的にこの方法を使用しています。私のチームは Subversion リポジトリを使用していますが、チームの何人かの開発者 (私を含む) は、ローカル マシンで git を実行して、Subversion が実行しない (または簡単に実行できない) より高度な処理を実行しています。あなたのように長期的なブランチを維持することはありませんが、複数の短期的なブランチを使用して、それらの間で変更をマージすることがよくあります。
ブランチとマージに関する Subversion の典型的な使用例の詳細については、Subversion bookを参照してください。