バージョン管理システムSubversionのインストール、初期設定、Tipsなど。

svnserve

svnserveデーモンを起動させるための設定方法。 ここではローカルネットワーク内からのアクセスのみを許可する条件で設定を行う。

まずはsvnserveを動作させるためのユーザ(ここではsvnとする)を作成する。

useradd svn

続いてリポジトリを格納するルートディレクトリ(ここでは/srv/repos)を作成する。 svnserveが書き込めるようにオーナをsvnにしておく。

mkdir /srv/repos
chown -R svn:svn *

/etc/servicesにsvnのサービス名と使用ポート番号が記述されていることを確認する(もしなければ追記する)。

/etc/services
svn   3690/tcp  subversion  # Subversion protocol
svn   3690/udp  subversion

/etc/hosts.allowに下記の内容を追記し、内部ネットワークからの接続のみを許可する。

/etc/hosts.allow
svnserve : 192.168.0. 127.0.0.1

また、iptablesなどを使ってファイヤーウォールの設定がされている場合は、3690番のポートを忘れずに空けておくこと。

続いて、inetdもしくはxinetdでsvnserveを起動するための設定を行う。

xinetd経由でsvnserveを起動する場合

xinetdの設定をするために、/etc/xinetd.d配下にsvnというファイルを作成し、下記の内容を書き込む。

/etc/xinetd.d/svn
service svn
{
        disable         = no
        socket_type     = stream
        wait            = no
        user            = svn
        server          = /usr/bin/svnserve 
        server_args     = -i -r /srv/repos
        log_on_failure  += USERID
        only_from       = 192.168.0.0/24 127.0.0.1
}

設定項目の意味は次の通り。

user
svnserveを実行するユーザ。
server
svnserveへのフルパス。
server_args
svnserveに渡す引数。 「-r /srv/repos」でリポジトリのルートディレクトリを/srv/reposに設定している。
log_on_failure
接続に失敗した場合、ユーザ名をログに記録する。

続いて、chkconfigコマンドを使ってsvnserveを起動できるようにする。

# svnserveを起動するようにする
chkconfig --add svnserve 

# 設定が反映されているか確認する
chkconfig --list svnserve

上記のコマンドを打ったあと、次のように表示されればOK。

svnserve:       on

起動設定が整ったところで、xinetdを再起動する。

service xinetd restart

telnetでsvnserveに接続して、次のようなメッセージが表示されればsvnserveが正常に動作していることが確認できる。

$ telnet localhost svn
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline svndiff1 absent-entries ) ) )
Connection closed by foreign host.

inetd経由でsvnserveを起動する場合

/etc/inetd.confにsvnserveの起動パラメータを追記する。 xinetdの場合と同様、「-r /srv/repos」でリポジトリのルートディレクトリを/srv/reposに設定している。

/etc/inetd.conf
svn stream tcp nowait svn /usr/sbin/tcpd /usr/bin/svnserve -i -r /srv/repos

起動設定が整ったところで、inetdを再起動する。

/etc/init.d/openbsd-inetd restart

telnetでsvnserveに接続して、次のようなメッセージが表示されればsvnserveが正常に動作していることが確認できる。

$ telnet localhost svn
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
( success ( 1 2 ( ANONYMOUS ) ( edit-pipeline svndiff1 absent-entries ) ) )
Connection closed by foreign host.

リポジトリの作成・設定

まずはリポジトリを作る。 ここではsandboxというリポジトリを/srv/reposに作成する。

# svnになる
su svn
# svnadmin createでリポジトリを作成
svnadmin create /srv/repos/sandbox

続いて、リポジトリのアクセス設定を行う。 リポジトリを作成すると自動的にconfディレクトリが作成される。 その中に次の三つのファイルが作成される。

svnserve.conf
svnserve経由でのリポジトリへのアクセス制限。 ユーザ設定ファイル・アクセス設定ファイルの指定など。
passwd
ユーザとパスワードの指定。
authz
ユーザごとのアクセス設定。

まずはsvnserve.confの設定例。

[general]
anon-access = none          # Anonymous(匿名)ユーザのアクセスを許可しない
auth-access = write         # 認証済みユーザには書き込み権限を与える
password-db = passwd        # パスワードファイルをpasswdとする
realm = sandbox             # リポジトリの説明(適当でOK)

anon-access、auth-accessに設定できる値は次の三つ。

none
アクセスを許可しない
read
読み込み権限を与える
write
読み込み、書き込みの両方の権限を与える

続いてpasswdの設定例。 リポジトリにアクセスするユーザの数だけ「ユーザ名=パスワード」の形式で記述する。

[users]
smdn=password

authzについては省略。 passwdファイルの編集が終わったら、アクセス権限をsvnだけに設定して、他のユーザからアクセスできないようにする。

cd /srv/repos/sandbox/conf
chmod 600 passwd
chown svn:svn passwd

ここまでで設定は完了。 作成したリポジトリをチェックアウトできるようになる。

$ svn co svn://localhost/sandbox/ ./sandbox
認証領域: <svn://localhost:3690> sandbox
'smdn' のパスワード: (passwdで指定したパスワードを入力)
リビジョン 0 をチェックアウトしました。

$ svn info ./sandbox
パス: sandbox
URL: svn://localhost/sandbox
リポジトリのルート: svn://localhost/sandbox
リポジトリ UUID: a3c65e7f-1127-41a2-baf2-0f721aaea87c
リビジョン: 0
ノード種別: ディレクトリ
準備中の処理: 特になし
最終変更リビジョン: 0
最終変更日時: 2009-11-21 05:08:44 +0900 (土, 21 11月 2009)

Sponsored Link

svnsync

svnsyncでリポジトリのミラーを作成する方法。

まずシンク(ミラー先)リポジトリを作成。 作成したら、必要に応じてconf/authz, conf/passwdなどを変えておく。

svnadmin create sync

続いて、リポジトリ内のhooksディレクトリにあるpre-revprop-change.tmplとstart-commit.tmplをコピー、編集してsvnsyncするユーザのみアクセスできるようにする。

cd sync/hooks
cp pre-revprop-change.tmpl pre-revprop-change
chmod u+x pre-revprop-change
cp start-commit.tmpl start-commit
chmod u+x start-commit

それぞれのファイルの内容は次のとおり。 svnはsvnsyncを実行するユーザ。

pre-revprop-change.sh
#!/bin/sh
USER="$3"

if [ "$USER" = "svn" ]; then
  exit 0
else
  exit 1
fi
start-commit.sh
#!/bin/sh
USER="$2"

if [ "$USER" = "svn" ]; then
  exit 0
else
  exit 1
fi

svnsync initでシンクリポジトリを初期化。

svnsync init file:///srv/sync/ file:///srv/repos/project/
リビジョン 0 の属性をコピーしました。

svnsyncを実行したとき、

svnsync: リポジトリが、リビジョン属性を変更できるようにはなっていません。
管理者に pre-revprop-change フックを作成するよう頼んでください

と表示される場合は、フックの設定に誤りがある。

初期化がうまくいったら、svnsync syncでリポジトリを同期する。

svnsync sync file:///srv/sync/
リビジョン 1 をコミットしました。
リビジョン 1 の属性をコピーしました。
リビジョン 2 をコミットしました。
リビジョン 2 の属性をコピーしました。
ファイルのデータを送信しています .....
リビジョン 3 をコミットしました。
リビジョン 3 の属性をコピーしました。
  :
  :

あとは同期したいタイミングでsvnsync syncを繰り返す。

TortoiseSVN

TortoiseSVNの使い方。

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

TortoiseSVNの設定ファイルを編集することで、ファイルをリポジトリに追加する時点で自動的に属性を付与させることができる。 これにより「$Date: 2010-09-01 01:33:12 +0900 (水, 01 9月 2010) $」などが自動的に日付に展開されるようになる。 また、拡張子から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: index.xhtml 935 2010-08-31 16:33:12Z smdn $」と書いておくと次のように展開されるようになる。

$Id: index.xhtml 935 2010-08-31 16:33:12Z smdn $

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

Tips

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

タグやブランチを作成するには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"

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

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

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

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

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

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

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

  1. 新しいリポジトリ名で現在のリポジトリの複製を作る
  2. 現在のリポジトリを削除する

という手順で変更できる。

svnadmin create repo_new
svnadmin dump repo_old | svnadmin load repo_new
rm -rf repo_old

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

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

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

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

/
|-- mod_foo/
`-- mod_bar/

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

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

svnadmin dump repo > repo.dump
 repo.dump]]>

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

svndumpfilter include mod_foo/ --drop-empty-revs --renumber-revs < repo.dump > mod_foo.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
もとのリビジョン属性を維持する(リビジョン属性はフィルタしない)

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

あるバージョンの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

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

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

/
|-- 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."
 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."]]>