svn:externals が設定されている状況で簡単に branch を切る
svn の branch は svn copy だけで簡単に作成できますが、厄介なのが外部項目の参照(svn:externals)です。
svn 1.4 までは、この外部項目が絶対パスでしか指定できなかったため、
と手間がかかりました。
svn 1.5 では相対パスの指定が可能になったため、ずっと簡単に branch を作成することができるようになりました。とはいえ、諸諸 trap がありましたので、手順を紹介。
ちなみに私は極力 URL 指定で branch を切ったりせず、ワーキングコピーで作業するようにしています。
URL 指定の結果はサーバ内部だけで処理が進んでしまい、作業の結果で本当に test をパスするかが怪しいと思っているので。また、過去 svn のリポジトリ構成が複雑過ぎたため、 URL 指定だと間違いが頻発してしまったというのも理由のひとつです。
事前の準備
branch を切りやすい構成にする。
相対パスで branch を切りやすくするためには、以下のような構成にします。
- trunk
- project1
- project2
- common
- branch
- tags
- milestone1
- project1
- project2
- common
- milestone2
- project1
- project2
- common
- milestone1
逆の project1, project2, common を root directory に置く方法は、この場合はとれません。
どちらを採用すべきか?は、
- project1, project2 がほぼ一体の組の場合は、trunk, branch, tags が root に
- project1, project2 にあまり関連性がない場合は、 project1, project2 が root に
するべきではないかと思います。
今回の場合は、common/lib を project1 と project2 で共有するため、前者に該当します。
branch を切る
svn copy で branch を作成
branch は通常の svn copy にて行います。
$ svn copy trunk branches/bug_no514
branch を作成したら、 branch の project1/lib に移動して svn info を確認してみると、
branch の project1/lib は trunk の common を参照しています。
$ svn info branches/bug_no514/project1/lib パス: branches/bug_no514/project1/lib URL: https://svn.foo.com/trunk/common/lib # ← ココ :
どうやら svn copy で copy した場合は、 svn:externals の実際の参照先は copy 元と同じ場所のままでコピーしてしまうようです。
しかしながら、 svn propget svn:externals で設定を確認すると、 正しく ../common/lib が参照されています。
$ svn propget svn:externals branches/bug_no514/project1 ../common/lib lib
すなわち、設定(属性)と実体(ディレクトリ)が不整合な状態になっています。次でこれを解消します。
一旦 commit する。
次の作業に進むにあたり、一回 commit が必要なので行います。
設定(属性)と実体(ディレクトリ)が不整合を解消する
2 つ対応方法があります。
- working copy 上の branch を一旦すべて削除して、再度 checkout する。
- 上記以外の方法で対応する。
上記の 1. は簡単なので、 2. の対応方法を紹介します。
以下のように誤った参照を行っているディレクトリを削除し、その後 svn up で復元します。
$ cd branches/bug_no514 $ rm -rf `svn st | egrep '^X' | awk '{print $NF}'` $ svn up
以上で svn:externals の書換えを行わずに branch の作成が完了します。
trunk へのマージを行う際も svn:externals が破壊されることがないので、
branch/merge が相当手軽に行えるようになります。