Subversionで外部参照をする方法

リポジトリシンボリックリンクみたいなことができる、外部参照という機能の使い方で、作法のところでかなりハマッタので記録に残しておきます。

結論

before
pj_top
├─src
└─ext

という状態のときに、http://path/to/target/dir/or/reposを外部参照するext_libというディレクトリを作って

after
pj_top
├─src
└─ext
    └─ext_lib

のような状態にしたい場合は、ext_libディレクトリを作ったりしないでbeforeの状態のままで、

svn propset svn:externals 'ext_lib http://path/to/target/dir/or/repos' ext

を実行するだけ。TortoiseSVNなら、extディレクトリのプロパティにsvn:externalsのエントリで

ext_lib http://path/to/target/dir/or/repos

を設定するだけ。これだけ。
あとはupdateなり更新なりすればhttp://path/to/target/dir/or/reposのファイルを取得できます。
リビジョン指定もできるらしいので、特定の状態のものを常に参照するということもできるみたいです。(未検証)
もしくはタグをきっておいて、そいつを参照するようにするとか。

試したこと

先にワーキングコピーにext_libディレクトリを作ってからやるのかと思い、

  1. ext/ext_libディレクトリ作成
  2. ext/ext_libディレクトリをコミット
  3. extディレクトリにsvn:externalsをpropset

とやったら、propsetをコミットするところで以下のエラーが発生。

Error: コミットに失敗しました (詳しい理由は以下のとおりです):  
Error: ファイルまたはディレクトリ '.' はおそらくリポジトリ側と比べて古くなっています  
Error: The version resource does not correspond to the resource within the transaction.  Either the requested version resource is out of date (needs to be updated), or the requested version resource is newer than the transaction root (restart the commit).  

よくわからなかったので、一端revertして、再度、propset。そしたら、正常にコミット終了。
設定完了したのかなーと思って、extディレクトリでupdateをかけると、

External: C:\pj_top\ext\ext_lib
Error: 作業コピー 'C:\pj_top\ext\ext_lib' はロックされています
Error: Please execute the "Cleanup" command.

というエラーが出力されてしまった。cleanupしろと書いてあるのでcleanupしてみたけど、変化無しだし。
ここで大きく悩んでネットをさまよってたけど、http://svn.haxx.se/users/archive-2006-08/1349.shtml で同じことに悩んでるひとの投稿を読んでるうちに冷静になってきて、ようやく上記の正しい手順を試すことに気付いて、なんとか設定することができました。

番外編 作業コピーのネスト

作業コピーってネストできるんですね。

working_copy_1
├─src_1
└─lib_1
working_copy_2
├─src_2
└─lib_2

みたいな状況のときに、ローカルのディレクトリを移動させて、

working_copy_1
├─src_1
└─lib_1
└─working_copy_2
    ├─src_2
    └─lib_2

みたいな感じにしても、互いに影響を与えずにそのまま問題なく使い続けられます。working_copy_2の下で変更がある状態で、working_copy_1をコミットしても、working_copy_2の下の変更はコミットされたりしません。
subversionすごい!