Subversion 1.5への移行
Subversionの1.5より前のバージョンでは、内部ではリビジョン毎に同一ディレクトリにファイルが作成されるため、リビジョン数が大きくなるとかなり不安な状態になってしまう。*1
しかし、バージョン1.5からはshardingという仕組みが導入され、1000リビジョン毎に一階層深いディレクトリにファイルが作られるようになったので多い日も安心。
Improved support for large deployments on FSFS, via sharding
1.5では他にも新しい機能がいくつか追加されており、特にマージ関連の機能追加(Merge tracking)がうれしいのでバージョンアップしたいのだが、古いバージョンのクライアントが混在した場合にどうなるかが不安なので調べてみた。
検証に使用したのは以下のバージョン。
$ svn --version svn, バージョン 1.5.3 (r33570) コンパイル日時: Oct 11 2008, 19:03:46
$ svn --version svn, バージョン 1.4.2 (r22196) コンパイル日時: Mar 14 2007, 20:55:55
それぞれMacPortsとCentOS 5.2での最新パッケージ。
Merge trackingを試してみよう
旧バージョンでの検証の前に、とりあえず新機能のMerge trackingを試してみよう。
サンプルとして svn://svn-server/trunk に rails のプロジェクトを作ってみた。
ブランチ作成
[~] $ svn copy svn://svn-server/trunk svn://svn-server/branches/first-test
trunkの作業コピーで適当なコントローラを作成
[~/trunk] $ ./script/generate controller -c login [~/trunk] $ svn ci
first-testの作業コピーで適当なコントローラを作成
[~/first-test] $ ./script/generate controller -c profile [~/first-test] $ svn ci
first-testの作業コピーにtrunkをマージ
[~/first-test] $ svn merge svn://svn-server/trunk --- r2 から r4 までを '.' にマージしています: A test/functional/login_controller_test.rb A app/helpers/login_helper.rb A app/controllers/login_controller.rb A app/views/login
おぉ!
さらにtrunkの作業コピーで適当なコントローラを作成
[~/trunk] $ ./script/generate controller -c message [~/trunk] $ svn ci
もう一度first-testの作業コピーにtrunkをマージ
[~/first-test] $ svn merge svn://svn-server/trunk --- r5 から r6 までを '.' にマージしています: A test/functional/message_controller_test.rb A app/helpers/message_helper.rb A app/controllers/message_controller.rb A app/views/message
おおぉ!
手動でリビジョンを指定したり記録したりする必要がないぞ!
マージしたリビジョンはsvn:mergeinfoプロパティに記録されていた
[~/first-test] $ svn propget svn:mergeinfo /trunk:2-6
最後にfirst-testブランチからtrunkへのマージ
$ svn merge --reintegrate svn://svn-server/branches/first-test --- リポジトリ URL 間の差分を '.' にマージしています: A test/functional/profile_controller_test.rb A app/helpers/profile_helper.rb A app/controllers/profile_controller.rb A app/views/profile U .
やったー
ただし、ブランチを作成してからtrunkにマージするまでの間にどちらかでディレクトリの移動(名前変更)又はコピーが行われていると、最後のマージで失敗してしまう。
[~/trunk] $ svn merge --reintegrate svn://svn-server/branches/first-test svn: Cannot reintegrate from 'svn://svn-server/branches/first-test' yet: Some revisions have been merged under it that have not been merged into the reintegration target; merge them first, then retry.
その場合は以前と同じ方法でマージを行えば問題ない
[~/trunk] $ svn merge svn://svn-server/trunk@11 svn://svn-server/branches/first-test@11 .
古いバージョンでのマージ
ブランチ作成
[1.5:~] $ svn copy svn://svn-server/trunk svn://svn-server/branches/second-test
trunkの作業コピーで適当なコントローラを作成
[1.5:~/trunk] $ ./script/generate controller -c star [1.5:~/trunk] $ svn ci
second-testの作業コピーで適当なコントローラを作成
[1.5:~/second-test] $ ./script/generate controller -c bookmark [1.5:~/second-test] $ svn ci
1.4クライアントでsecond-testの作業コピーにtrunkをマージ
[1.4:~/second-test] $ svn merge -r 17:19 svn://svn-server/trunk A test/functional/star_controller_test.rb A app/helpers/star_helper.rb A app/controllers/star_controller.rb A app/views/star
trunkの作業コピーへさらに適当なコントローラを追加
[1.5:~/trunk] $ ./script/generate controller -c anond [1.5:~/trunk] $ svn ci
1.5クライアントでsecond-testの作業コピーにtrunkをマージ
[1.5:~/second-test] $ svn merge svn://localhost/trunk --- r17 から r21 までを '.' にマージしています: A test/functional/anond_controller_test.rb A test/functional/star_controller_test.rb A app/helpers/star_helper.rb A app/helpers/anond_helper.rb A app/controllers/anond_controller.rb A app/controllers/star_controller.rb A app/views/star A app/views/anond
重複してマージが行われてしまった。ファイルに一切変更がなければよきに計らってくれるみたいだけど、何らかの変更があると
--- r17 から r22 までを '.' にマージしています: A test/functional/anond_controller_test.rb A test/functional/star_controller_test.rb A app/helpers/star_helper.rb A app/helpers/anond_helper.rb A app/controllers/anond_controller.rb 'app/controllers/star_controller.rb' で競合が見つかりました。 選択: 延期 (p), 全差分 (df), 編集 (e), ヘルプでその他のオプションを表示 (h) : p C app/controllers/star_controller.rb 'app/views/star' を飛ばしました A app/views/anond
衝突する。
マージ作業を古いクライアントと混じりながら行う事は考慮されていないようだ。
まとめ
- Merge trackingは便利
- ブランチ作るならクライアントも1.5にした方が良い
- 1.4以前でマージをすると不幸になる
*1:FSFSの場合