意味の分からない人もいるかもしれないのでまずは svn switch が何ものなのかという話から。
help を見てみよう。
$ svn help switch
switch (sw): Update the working copy to a different URL.
usage: 1. switch URL[@PEGREV] [PATH]
2. switch --relocate FROM TO [PATH...]
...
これは基本的に working copy の branch, trunk などを切り替えるために使う。CVS 時代には update 時に revision ではなく tag を指定することで branch を切り替えるという方法しかなかった1のだが、svn では明示的にリポジトリの中の URL を指定して switch するという、update とは別の branch 切り替え用の操作が導入された。それが svn switch である。
svn switch は指定した repository 上の特定のパスと working copy 上の特定のパス(あるいはカレントディレクトリ)を結びつけて動作する。
実はこれ、ディレクトリツリーの一部だけ別な branch にするという操作が可能なのだ。
何を大げさなと思うかもしれないけど、改めて考えるとディレクトリツリーの一部だけが別なストリームに属している状態というのはとても奇妙である。
.
|-- bin
|-- lib
|-- templates
| |-- bin
| `-- lib <--
`-- test
`-- script <--
`-- foo
<-- の部分だけ別 branch なんてことが可能
いや、実は自分も昔、ディレクトリツリーの一部だけ branch に入れたいなーとよく思っていた。これを思ったのはそもそもまともにモジュール化されていない巨大な repository を Subversion
- Trac に移行した直後からしばらくの間。何しろでかいのであまり cp したくないし、CVS の時代には branch や tag などの情報はツリーに対してではなく個々のファイルに属していたので、一部のファイルだけ branch を切るということが実際によく行われていた。2
当時はこれで妥当だと思ってた。branch 上の作業に必要のないファイルを除外して最小セットで編集できた方がディスクスペース的にも効率がいいし、repository <-> working copy 間の転送量も減るから速いし、後から ViewCVS などで見直したときにも余計な情報が目に入ってこなくて嬉しいと。
でもいま考えるとテストの自動化などをしようとしたときにうまくないよね、これ。ツリーの特定の一部だけ違う branch なんてことが許されたら、どこがどの branch か分からなくなっちゃう。言い直すとどういう状態がその branch を動作させるのに適切な状態か分からない。
branch なんだから自動化できなくていいんじゃない?と思うかもしれない。そうか、でも考えてみてほしい。
自動化できないということは実は人間の作業的にも優しくないのだ。
ツリーのどことどこを switch したら開発が始められるのかをどこかに書いておかないと、その branch で作業を始められない。これは厳しい。本当に厳しいよ。branch がツリー全体を含んでいてくれれば何も考える必要がない。svn switch あるいは svn co 一発で済む。なんて快適!
実は。
svn では一部だけ別 branch にするのは案外面倒くさい。普通に svn cp すると指定パス以下全部 cp されるようになっている。一部だけ別 branch の状態を作るには強い意志を持ってとても面倒くさくて慎重な copy 作業が必要なのだ。でもすべてのプログラマが怠惰という美徳を身につけているわけではない。CVS 時代のバッドなノウハウを頑なに維持しようとする勤勉な人だっているのだ3。
なぜ分散SCMが大流行している2009年になって CVS 時代を振り返りながら Subversion の話なんかしているんだとお前は、と思うかもしれない。しかし今回の問題は自分の中でもあまり明確になっていなくて、
なんとなく自分のノウハウが変わっていった
状態だった。これはいけない。明確にしておかないといけない。丸ごと別 branch にしなさいと。これを痛感した理由は
せっかくの setup 用のツールが branch から外れてて開発開始までの行程が全部手作業になってめちゃくちゃ面倒だった
からだ。
恐ろしいだろう? でも実際にあった話なんだぜ。手作業が面倒だから自動化するツールを repository に突っ込んであるのにそれがなくなっちゃってるんだ。しかも善意のおかげで。でもその勤勉さが自分以外のみんな4にも勤勉な作業を強制しているんだってことが分からなきゃダメだよ。でないと君を手助けすることだってできやしない。
しかもだ。
元に(例えばツリー全体を trunk に)戻すのも大変だ。
どことどこが別 branch になっているか覚えているかい?
もう一度書く。丸ごと別 branch に入れろ。それが遅くてたまらない場合はもうその repository が根本的に間違ってるか repository への接続方法など周辺の要因か Subversion の限界だ。
[追記] とりあえず working copy の状態をチェックする方法を思いついた。
Twitter / wtnabe: 魔の svn switch に対抗できるかもしれない …
find . -type d -a ! -regex '.*\.svn.*' -exec svn info {} \; | grep URL
ってやったら各ディレクトリがどの URL と結びついているかはチェックできる。これで trunk に commit したつもりが閉じたはずの branch に commit してた、なんて事故を防げる。
[追記] ツッコミいただいた。こっちの方が簡単。
svn stat | awk '$1 == "S"'
svn stat は -v があってもなくても一緒。これはいいな。ぐっと楽になった。