SVN を使いやすくするシェルスクリプト
こんばんは、naoya です。
ウノウでは、プログラムのソースコード管理に SVN を使っていますが、日々の開発の中でずっと SVN コマンドを使い続けていると、SVN コマンドの入力がめんどうになってくる場面があります。
今日は、SVN コマンドの入力を簡略化するために、僕が作成したシェルスクリプトをいくつか紹介します。
1) プログラムのリビジョンを一つ前に戻す
誤ってプログラムしたり、プログラムを変更してコミットしたあと、一つ前のバージョンに戻したい場合がたまにあります。そんなときは、SVN コマンドの場合は、次のように入力します。
svn merge -r 上書き対象のリビジョン番号:戻すリビジョン番号 対象のファイル名
このコマンドを使うには、対象ファイルのリビジョン番号を svn info で調べないとリビジョンを指定することができないので、次のようなスクリプトを作ってみました。
#!/bin/shif [ $# == 0 ]; then
echo "Usage:" svn_revert [svn target file name]
exit -1
fiif [ ! -e $1 ]; then
echo "Could not found file. -" $1
exit -1
fiSVN=/usr/local/bin/svn
grep_rev='grep Revision:'export LANG=
revision=`$SVN info $1 | $grep_rev | awk '{printf "%s\n", $2}'`
prev_revision=`expr $revision - 1`$SVN merge -r $revision:$prev_revision $1
echo "svn reverted '$prev_revision' done."
やっていることは、とても単純で対象のファイルのリビジョンを調べて、その一つ前のリビジョン番号のファイルにしています。(そのままですね。。。)
このシェルスクリプトは、見て分かるとおり grep, awk, expr が必要です。どうして、awk を使ったのかというと、深い理由はあまりありませんが awk で遊んでみたかっただけです。なお、リビジョン番号が 1 だったときなどのエラー処理はしていませんので、注意して使ってください。
このシェルスクリプトは引数にリビジョンを一つ戻したいファイル名をします。実行した後は、コミットすれば一つ前のリビジョンにファイルを戻すことができます。しかも、元に戻したリビジョンが表示されるので、コミットログに分かりやすく残すことができます。
2) トランクの変更をブランチにマージする
僕が今担当しているプロジェクトでは、トランクとブランチに別れて開発しています。僕はおもにブランチの開発を担当していますが、並行で行われているトランクの変更をブランチ側にマージしなければいけません。
僕は初めて SVN でブランチで開発していたので、トランク側での変更をブランチ側にマージするときに何度もミスをしてしまったのですが、やっと正しいマージの方法を理解したので忘れないように、次のようなシェルスクリプトを書いてみました。
#!/bin/shif [ $# == 0 ]; then
echo "Usage:" svn_merge [trunk head revision]
exit -1
ficd ~/SVNリポジトリの場所
SVN=/usr/local/bin/svn
$SVN merge -r ブランチをしたときのトランクのリビジョン番号:$1 マージ元のトランクのURL
これは、シェルスクリプトで書くまでもなくコマンドのエイリアスでも十分だと思いますが、シェルに依存しないようにシェルスクリプトにしてみました。このシェルスクリプトのポイントは、ブランチをしたときのトランクのリビジョン番号を設定することです。
インターネットで調べてみると、ブランチの変更をトランクへマージする SVN コマンドの使い方はよく書かれていますが、その逆のトランクの変更をブランチにマージする SVN コマンドの使い方があまり情報がなくて、苦労しました。
あとは、トランクとブランチの両方を変更する場面に直面したときに、トランクとブランチを切り替えられるシェルスクリプトを作ってみたり、トランクとブランチの差分をとるシェルスクリプトを作ってみました。これは、SVN コマンド一つでできますが、SVN リポジトリの URL が長いので、シェルスクリプトにすると便利です。
まだこれだけのスクリプトだと不十分で、次のようなことを改善できる方法があればぜひ教えてください。
・衝突してしまったファイルを手動で一通り修正した後、svn resolved で衝突を改善するときにまだ修正もれがあれば通知してくれるプログラム
・コミットする前に、デバッグコード(たとえば、コメントに // DEBUG や // FIXME と入っているコードがコミットできないようする commit フックプログラム(たしか、CSV では衝突したプログラムはコミットできないようになっていたと思いますが、svn では設定によるのでしょうか?)
業務が忙しくなればなるほどこういう小さな改善が効果をもたらしてくれると思うので、時間が作りながら日々の業務の効率を上げていきたいと思います。

コメント
1)
直前のリビジョンは "PREV" で指定できたと思います。
svn merge -r PREV:HEAD
2)
これも引数はいらなくて HEAD でいけるんじゃないかな
個人的にはよほどタイプ数が多いコマンドでない限り、基本的にはヒストリを使います。ctrl+r で検索、zsh ならコマンド途中まで打って alt+p で特定コマンドのヒストリが辿れるのが素敵です。
> ・衝突してしまったファイルを手動で一通り修正した後、svn resolved で衝突を改善するときにまだ修正もれがあれば通知してくれるプログラム
svn resolved するってことは衝突を回避したということなので、更に検知するのは本来なら本末転倒なんだけど、
やるなら ">>>>>>>>>>>> .mime" とか grep して見つかったらコミットをキャンセルするという感じかな。
pre-commit にスクリプト仕込めば簡単にできると思います。
テキストファイルだけに適用するようにしないとダメですね。
> ・コミットする前に、デバッグコード(たとえば、コメントに // DEBUG や // FIXME と入っているコードがコミットできないようする commit フックプログラム
これも同じように pre-commit にスクリプト仕込めば結構簡単にできそう。
この辺のルール作りは作業している人の間でコンセンサスをとる必要がありますね。
> たしか、CSV では衝突したプログラムはコミットできないようになっていたと思いますが、svn では設定によるのでしょうか?
衝突したままではコミットできないはず。
svn resolved してないですか?
投稿者: masato | 2006年8月21日 19:46
masatoさん、コメントありがとうございます。
1) 実は、PREV があることは、このスクリプトを作ってから知りました。
svn merge -r HEAD:PREV ファイル名
で前のリビジョンに戻すことができました。
このコマンドなら、コマンドのエイリアスで十分ですね。
2) 引数に HEAD を指定してみて試してみましたがうまくいきませんでした。この方法で、マージしているとトランクの変更によってはブランチ側で何も変更しなくても衝突してしまうので、仕方がないのだと思っています。
>svn resolved するってことは衝突を回避したとうことなので、更に検知するのは本来なら本末転倒なんだけど、やるなら ">>>>>>>>>>>> .mime" とか grep して見つかったらコミットをキャンセルするという感じかな。pre-commit にスクリプト仕込めば簡単にできると思います。テキストファイルだけに適用するようにしないとダメですね。
hook に仕掛けるのは考えていたのですが、svn resolved で衝突を解除したとき、まだ修正もれ">>>>>>>>>>>> .mime"があるときは衝突を解除できないようにするのが一番だと思っていますが、svn resolved には hook がないようですので、pre-commit hook が一番いいと思います。
今までミスをしているのは、衝突したコードを手動で一通り修正した後、まだ修正もれ(衝突したままのコード)があるにも関わらずコミットしてしまったことなので、自分で十分で注意するのはもちろんですが、ツール側の手助けがあった方がミスを減らせると思います。
投稿者: naoya | 2006年8月22日 12:39