svnコマンド、Subversionクライアントに関するTips。

§1 svn

§1.1 タグ・ブランチを作成する

タグやブランチを作成するにはsvn copyでtrunkをコピーする。 例えば、現在のtrunkの状態にtags/release-1.0という名前を付けるには次のようにする。

svn copy svn://repos/someproject/trunk svn://repos/someproject/tags/release-1.0 -m "version 1.0"

§1.2 属性(プロパティ)を付ける

バージョン管理されているファイルに属性を設定するには、svn propsetを使う。

svn propset svn:keywords "URL Rev Id Date Author" sample.c

他にも属性に関連するコマンドには次のようなものがある。

propget
付与されている属性の値を表示する
proplist
付与されている属性を一覧にして表示する
propdel
付与されている属性を削除する
propedit
外部エディタを使って属性の値を編集する

一度削除すると(作業コピーが残っていない限り)当然復元できないので、復元したい場合などは削除する前にsvnadmin dumpでダンプファイルを忘れずに作っておく。

§1.3 GNOME keyringでのユーザ認証が要求される

Ubuntu 11.10で起きた問題。 GNOME keyringを使用していないのに関わらず、svnコマンドでの認証で次のようなエラーが表示される。

$ svn commit hoge.txt
Password for '(null)' GNOME keyring: 
svn: コミットに失敗しました (詳しい理由は以下のとおりです):
svn: GNOME Keyring is locked and we are non-interactive

~/.subversion/configのauthセクションに以下の内容を追記して認証プラグインを無効にすると、

~/.subversion/config
[auth]
password-stores =

先のエラーは表示されなくなる。

$ svn commit hoge.txt
'smdn' のパスワード: 
送信しています              hoge.txt
ファイルのデータを送信しています .

/.gnome2/keyrings/login.keyringを削除することでも解決できる模様(未確認)。

§2 svnadmin

§2.1 リポジトリをリネームする

リポジトリをリネームする場合は、

  1. 新しいリポジトリ名で現在のリポジトリの複製を作る
  2. svn switch --relocateで作業コピーのURLを更新する
  3. 現在のリポジトリを削除する

という手順で変更できる。 例として、リポジトリと作業コピーがある状態でリネームする場合は次のようにする。

svnadmin create repo_old # リネーム前のリポジトリを作成
svn co svn://localhost/repos/repo_old repo # リネーム前の作業コピー

上記のような手順で作成したリポジトリrepo_oldと作業コピーrepoがあるとする。 まずは、リネームしたいリポジトリrepo_oldの複製を新しいリポジトリ名(ここではrepo_new)で作成する。

svnadmin create repo_new # リネーム後のリポジトリを作成
svnadmin dump repo_old | svnadmin load repo_new # リポジトリを複製

なお、svnadmin dump/loadではリポジトリのパーミッション、設定ファイル類はコピーされないので、忘れずにコピーする

chmod -R g+w repo_new
cp -ipr repo_old/conf/* repo_new/conf/

次に、svn switch --relocateで作業コピーのURLを更新する。 更新の前後でURLが変わり、リポジトリUUIDはそのままとなる点に注意。

$ svn info ./repo
パス: repo
URL: svn://localhost/repos/repo_old
リポジトリのルート: svn://localhost/repos/repo_old
リポジトリ UUID: 62890211-38d3-4356-9e41-f5a96cf7b558
リビジョン: 3

$ svn switch --relocate svn://localhost/repos/repo_old svn://localhost/repos/repo_new ./repo
$ svn info ./repo
パス: repo
URL: svn://localhost/repos/repo_new
リポジトリのルート: svn://localhost/repos/repo_new
リポジトリ UUID: 62890211-38d3-4356-9e41-f5a96cf7b558
リビジョン: 3

すべての作業コピーのURLの更新が終わったら、リネーム前のリポジトリを削除する。

rm -rf repo_old

§2.2 リポジトリの一部分を切り出す

ダンプファイルからリポジトリツリーの一部分を取り出したり除外したりするにはsvndumpfilterを使う。

/
|-- mod_foo/
`-- mod_bar/

例えば、上記のような構成のリポジトリから、mod_fooだけを切り出して一つのリポジトリを作成するには次のようにする。

まずリポジトリのダンプファイルを作成する。

svnadmin dump repo > repo.dump

続いて、このダンプファイルから、mod_fooだけを含むようにsvndumpfilterでフィルタする。

svndumpfilter include mod_foo/ --drop-empty-revs --renumber-revs < repo.dump > mod_foo.dump

後は、出来上がったmod_foo.dumpを新しいリポジトリにロードすることで、mod_fooだけを含むリポジトリを作成できる。

svnadmin create mod_foo
svnadmin load mod_foo < mod_foo.dump

svndumpfilterで指定できるオプションは次のとおり。

include
指定したパスを含む変更をフィルタして切り出す
exclude
指定したパスを除く変更をフィルタして切り出す
--drop-empty-revs
フィルタした結果、切り出すサブツリーに関係する変更がないリビジョンはダンプファイルに含めない
--renumber-revs
フィルタした結果に、新しくリビジョン番号を振り直す
--preserve-revprops
もとのリビジョン属性を維持する(リビジョン属性はフィルタしない)

§2.3 異なるバージョン間でのリポジトリ移動

あるバージョンのSubversionで管理されているリポジトリを、別のバージョンのSubversionで管理されている環境に移動する場合は、svnadmin dump/loadを使い次の手順で行う。

  1. バージョンAのsvnadminでリポジトリをダンプする
    svnadmin dump /path/to/repos > dumpfile
  2. バージョンBのsvnadminでリポジトリを作成
  3. バージョンBのsvnadminでダンプしたリポジトリをロードする
    svnadmin load /path/to/repos < dumpfile

§2.4 リポジトリを削除する

リポジトリを削除する場合は、svnadmin createコマンドで作成されるディレクトリを削除すればよい。 svnadminコマンドにはリポジトリを削除するためのコマンドは用意されていないので、rm -rで削除する。

リポジトリの作成
$ svnadmin create sandbox
$ ls 
sandbox
$ svnlook info sandbox/

2010-09-11 22:17:31 +0900 (土, 11  9月 2010)
0
作成したリポジトリの削除
$ rm -rf sandbox/
$ svnlook info sandbox/
svnlook: ファイル 'sandbox/format' を開けません: No such file or directory

§2.5 リポジトリと初期ディレクトリの構成を自動的に作成するスクリプト

定形のリポジトリを自動的に作成する目的で作成したスクリプト。 このスクリプトは、リポジトリを作成したあと次のような初期ディレクトリ構成をリポジトリにインポートする。

/
|-- README
|-- tags/
|-- branches/
`-+ trunk/
  |-- src/
  `-- bin/

また、設定ファイルのテンプレート.svnserve.confをコピーし、作成したリポジトリの設定ファイルに上書きする。

#!/bin/bash

# usage: makerepo.sh reponame

REPONAME=$1
REPOSDIR='/var/repos'
TEMPDIR='/tmp/repolayout'
TEMPLOGFILE="$REPOSDIR/tmp.txt"
LOGMESSAGE='imports initial directory layout'
SVNREPOFSTYPE='fsfs'
SVNREPOCREATE="/usr/bin/svnadmin create --fs-type $SVNREPOFSTYPE"
SVNREPOIMPORT="/usr/bin/svn import --file $TEMPLOGFILE"

#
# リポジトリを作成する
#
echo "creates repository '$REPONAME'"

$SVNREPOCREATE $REPOSDIR/$REPONAME

#
# 初期ディレクトリ構成(trunk, branches, tags, README)を作成する
#
echo "creates initial directory layout"

mkdir -p $TEMPDIR
cd $TEMPDIR
mkdir trunk branches tags
: > README

#
# trunk以下のディレクトリを作成する
#
echo "make source directory(y/n)"
read makesourcedir

if [ "$makesourcedir" = 'y' ]
then
  cd trunk
  mkdir bin src
  cd -
fi

ls -lR

#
# 初期ディレクトリ構成をリポジトリにインポートする
#
echo "imports initial directory layout to repository"

echo $LOGMESSAGE > $TEMPLOGFILE
$SVNREPOIMPORT . file://$REPOSDIR/$REPONAME
rm -rf /tmp/repolayout/
rm $TEMPLOGFILE

#
# リポジトリの設定ファイルのテンプレートをコピーする
#
echo "copies repository configuration file"
cp $REPOSDIR/.svnserve.conf $REPOSDIR/$REPONAME/conf/svnserve.conf

echo "finished."

§3 TortoiseSVN

TortoiseSVNの使い方。

§3.1 自動的に属性を着けるには

TortoiseSVNの設定ファイルを編集することで、ファイルをリポジトリに追加する時点で自動的に属性を付与させることができる。 これにより「$Date$」などが自動的に日付に展開されるようになる。 また、拡張子からMIMEタイプを判断させるようにすることも出来る。 以下はその設定方法。

まずエクスプローラ上で右クリックし、メニューからTortoiseSVN→Settingsの順に選択。 続いて出現する画面からGeneralを選択し、「Subversion configuration file」の横にあるEditボタン(赤い矢印の部分)をクリックする。

Subversion configuration file

テキストエディタが開いて設定ファイルの内容が表示されるので、次の内容を書き込む。

[miscellany]
enable-auto-props = yes # 自動的に属性をつけるようにする

[auto-props]
*.cpp = svn:keywords=Id Date Rev Author # 拡張子が.cppの場合は、コミット時に
                                        # Id, Date, Rev, Authorの各キーワードを展開する
*.h   = svn:keywords=Id Date Rev Author
*.png = svn:mime-type=image/png         # 拡張子が.pngの場合は、MIMEタイプをimage/pngに設定する
*.jpg = svn:mime-type=image/jpeg
*.bmp = svn:mime-type=image/bmp
*.psd = svn:mime-type=image/x-photoshop
*.ico = svn:mime-type=image/x-icon

この設定をした上で、たとえばファイル中に「$Id$」と書いておくと次のように展開されるようになる。

$Id: test.cpp 2550 2013-05-29 06:39:05Z smdn $

$Idのあとに続けて、順に「ファイル名、リビジョン番号、最終変更日時、最後に変更を行ったユーザ」の各値が展開される。