rcmdnk's blog

実用 Subversion 第2版

SVNでたまに忘れて困ることとか 便利にする方法とか。

@入りファイル

SVNでは@はリビジョン指定に使います。

$ svn rm file@aaa

というコマンドを打つと、aaaというリビジョンのfileを操作しようとします。 file@aaaというファイルにはなりません。

$ svn rm file\@aaa

のようにしてもaaaリビジョンのfile\ を見ようとします。

一方、svn add等はsvn add file@aaafile@aaaというファイルを 加える事ができたりするので、一度登録した後、後で操作しようとした時に 操作できなくて困ることがあります。

この様なファイルをいじるには、もう一つ@を加えればOK。

$ svn rm file@aaa@

これは

$ svn rm file@aaa@HEAD

と同じ意味になるので、通常何も付けない時のHEADからのrmと同じ意味になります。

ただ、SVNだけでなく、普通にコマンドラインで呼ぶときにもエスケープしなきゃいけなかったり することもあるので、 特別な理由がない限り普段から@なんて入ったファイル名を作るのは避けた方が無難です。

svnのdiff

以下のようなvimdiffのラッパースクリプトを用意します。

svndiff.sh
1
2
#!/usr/bin/env bash
vimdiff $6 $7

これをPATHの通ったディレクトリなどに置いておいて、 SVNのdiff-cmdに指定します。

diff-cmdに渡される引数は7つあって、 例えば現在居るディレクトリにChangeLogと言ったファイルがあって、 そのファイルでsvn diff ChangeLogすると以下の様な引数が渡されます。

  • $1: -u
  • $2: -L
  • $3: ChangeLog (revision 123)
  • $4: -L
  • $5: ChangeLog (working copy)
  • $6: .svn/text-base/ChangeLog.svn-base
  • $7: ChangeLog

となります。 -u-Ldiffコマンドのオプションで、つまり、デフォルトでは

$ diff diff -u -L "ChangeLog (revision 123)" -L "ChangeLog (working copy)" .svn/text-base/ChangeLog.svn-base  ChangeLog

というコマンドが呼ばれてることになります1

-uはdiffの出力をUnified形式(patchとかで使える形式)にするためのオプション、 -Lは入力ファイルのそれぞれのラベルを付けるためのオプション。

.svn/text-base/ChangeLog.svn-baseが現在のHEADバージョンに当たるもので (上ではHEADのリビジョン番号123)、 それと実際に作業しているChangeLogとの比較をしています。

なので、他のdiffツールを使いたい場合にも、 基本的に$6$7を引数として与えれば使えます。

diff-cmdの設定は~/.subversion/config

~/.subversion/config
1
2
[helpers]
diff-cmd = svndiff.sh

と設定しておけば

$ svn diff file

とするだけでdiffがvimdiffで見れる様になります。

デフォルトのdiffを使いたい場合には

$ svn diff file --diff-cmd diff

--diff-cmddiffコマンドを指定します。

もし、通常はデフォルトdiffを使いたくてたまにvimdiffを使いたい場合には、 ~/.subversion/configではdiff-cmdを指定せずに、 使いたい時だけ

$ svn diff file --diff-cmd svndiff.sh

としてあげればOK。

How to make diffs of SVN and Git files with vimdiff

ファイルだけチェックアウト

大量のファイルがあるレポジトリの一部のファイルだけを変更したり 見てみたかったりする場合、 全部を取るのが大変なので一部だけ取ってきたい場合があります。

この場合、ファイルだけいきなりチェックアウトする方法は無いので、 一度上のディレクトリをemptyでチェックアウトして その後でupdateを使って必要なファイルだけ取ってくることが出来ます。

$ svn checkout --depth empty svn://dir/repo/
$ cd repo
$ svn update file

とするとsvn://dir/repo/に大量のファイルやディレクトリがあっても、 svn://dir/repo/fileだけ取ってくることが出来ます。

プロテクト

作業中に他の人に変更されないように、lockコマンドでファイル単位で プロテクトをかけることが出来ます。 ただ、これはファイルごとでディレクトリごとする方法はありません。

また、この場合にもlock --forceで他人が取る事は可能。

この辺簡単に何とかできないかな、と思ってちょっと調べてみましたが、 結局サーバー側で設定したりするしかなさそう。

Path-Based Authorization

Cannot lock all files in directory using SVN - Stack Overflow

SVNコマンドメモ(Hishidama’s Subversion command Memo)

SVNで接続のチェック

SVNを使っててcheckout等で何か接続のせいとかで上手く出来ない場合、

$ export SVN_SSH="ssh -v "

としておくと接続にverboseモードのsshを使ってくれるので どこで認証がおかしくなってるか分かります。

~/.ssh/known_hostsが悪さをしてて、これを削除するか、 中にある該当ホストを消すとうまくいくことがよくあります。

関係ないけど気をつけよう、と言う話

SVNに限った話ではないですが、Webサイト等のソースをSVN等で管理してる場合、 それらの.svnディレクトリ等もそのまま公開場所に送ってしまって それらから情報が漏れてしまう、ということがちょっと前に話題になってました。

「.svn」「CVS」ディレクトリを狙ってWebサイトの非公開ファイルをゲット

Sponsored Links
  1. 加えて、出力の最初に

    Index: ChangeLog
    ===================================================================)
    

    みたいのが加わる。

Sponsored Links

« Firefoxで'このブラウザではJavaScriptが無効になっているか、サポートされていないようです。'と言われた octopress-gemojiのアップデート »

}