[ Topページへ戻る ]
2003.6.23よりアクセス
Subversionは、CVS(Concurrent Versions System)を改良したバージョン管理ツールです。使い勝手はCVSに非常によく似ています。
svn, svnlook, svnadmin, mod_dav_svn, svnserve, svnversion
$ svn checkout http://svn.example.com/repos/hello A hello A hello/build.xml A hello/Hello.java $ ls -a hello build.xml Hello.java .svn/ $
$ svn checkout http://svn.example.com/repos/hello/trunk hello :
trunkというディレクトリが生成されるのはいまいちなので、リポジトリ上のtrunk下にあるファイル・ディレクトリを作業ディレクトリのhelloディレクトリの下にチェックアウトします
$ svn commit Hello.java
$ svn update U Hello.java
記号の意味は以下の表のとおりです。
記号 | 内容 |
---|---|
U | ファイルがリポジトリの最新版に更新された |
A | ファイルが新規追加された |
D | ファイルが削除された |
R | ファイルが置き換えられた(同じ名前だが履歴上は別物) |
G | ローカルの修正とリポジトリの更新がマージされた |
C | ローカルの修正とリポジトリの更新が競合している |
競合が発生すると、いくつかのファイルが生成されます。aFileの場合、競合が発生すると、以下のファイルが生成されます。
$ svn add Greeting.java A Greeting.java $ svn commit Greeting.java
commit前に取り消しする場合は、svn revertを使用します。
$ svn info Greeting.java
$ svn status MM Greeting.java
Subversion 1.1までのデフォルトの形式でしたが、最近ではファイルシステム(FSFS)に置き換わり、あまり見ることはありません。
$ svnadmin create --fs-type bdb /home/svn_rep $ ls /home/svn_rep README.txt conf/ dav/ db/ format hooks/ locks/
リポジトリは、Berkeley DBを使用した場合、CVSのようにディレクトリ/ファイルが生で見れることはありません。hooks/には、例えばコミットした直後に動作するスクリプト、といったものが置かれます。confの下には、リモートからアクセスする際のアクセス権やパスワード設定に関する情報svnserve.confがあります。リモートから接続する場合、svnserve.confを適切に記述しておきます。
Berkeley DBを使用する場合、リポジトリの場所をNFSやSMBなどのネットワーク共有にすることはできません。Berkley DBはデータをメモリにマッピングするため、ファイルを複数CPUから共有すると不整合が発生します。
Subversion 1.2からデフォルトとなっている形式です。
$ svnadmin --fs-type fsfs create /home/svn_rep $ ls /home/svn_rep README.txt conf/ dav/ db/ format hooks/ locks/
$ svnadmin dump /home/svn_rep > svn_rep_backup_`date +%Y%m%d` * Dumped revision 0. * Dumped revision 1. * Dumped revision 2. : $
バックアップしたリポジトリを復元します。
$ svnadmin create /home/svn/svn_rep $ svnadmin load /home/svn/svn_rep < svn_rep_backup_20050401
Berkeley DBで作ったリポジトリをフルバックアップし、そのファイルをファイルシステムのリポジトリにリストア(load)してもOKでした。
バックアップには、conf/subversion.confファイルは含まれないので、設定ファイルは手動でバックアップを取る必要があります。
hello +--- build.xml +--- src +--- Hello.java
リポジトリ上、javaproj/hello に置く場合は次のコマンドを実行
$ svn import hello file:///home/svn_rep/javaproj
このとき、環境変数SVN_EDITORに設定したエディタが起動されます。ログを記述してエディタを終了すると、import処理が実行されます。
$ svn list file:///home/svn_rep
$ svn mkdir file:///home/svn_rep/cxxproj
$ svn delete file:///home/svn_rep/cxxproj
$ svn move -m "Log a message" file:///home/svn_rep/cxxproj/a.txt file:///home/svn_rep/cxxproj/sub/a.txt
$ svn move a.txt sub/a.txt A sub/a.txt D a.txt $ svn commit
$ svn move
以下の5つのキーワードが置換可能です。ただしデフォルトでは置換が無効となっています。
キーワード | 略語 | ||
LastChangedDate | Date | ||
LastChangedRevision | Rev | ||
LastChangedBy | Author | ||
HeadURL | URL | ||
Id |
$ svn propset svn:keywords "LastChangedRevision" Greeting.java
Windows Vistaならユーザーディレクトリ下の\AppData\Roaming\Subversionディレクトリ内にあるconfigファイルを設定します。
enable-auto-props = yes *.java = svn:keywords=Id *.sdoc = svn:keywords=Id
拡張子.java、.sdocのファイルをSVNで追加すると、キーワードIdの置換が有効になります。
WebDAV/deltaVプロトコルで通信する(HTTP1.1の拡張)
必要なもの:Apache httpd 2.0、mod_DAV、Subversion、mod_dav_svn
svnserveを実行する。デフォルトポートは3690。inetdに設定するか-dオプション付きでデーモンプロセス起動。
オプションなしでsvnserveを実行
svn://myhost/usr/local/repos/project
へのアクセスは、myhost上の/usr/local/repos/proj にあるリポジトリを参照。
-rオプション付きでsvnserveを実行(例:svnserve
-r /usr/local)
snv://myhost/repos/proj へのアクセスは、myhost上の/usr/local/repos/proj
にあるリポジトリを参照。
-Rオプション付きは書き込み不可
Solaris 10上でのsubversion設定手順
ネットワークからSVNサーバ経由で利用する場合、各リポジトリのルート直下のconfディレクトリにあるsvnserve.confを適切に記述する必要があります。
・プロジェクト間でリポジトリのデータの共有、移動を行うかどうか?
・コミット時の処理、認証、アクセス許可を同じにするかどうか?
を判断基準に同じリポジトリを使うか別リポジトリにするか判断します
Subversionでのブランチ作成は、単なるディレクトリのコピーです。
リポジトリ上に、trunk、branchesというサブディレクトリを設けるTipsが一般的です。2つ方法があり、良いと思う方を使えばよいようです。
repos +--- projA | +--- trunk | +--- branches +--- projB : +--- trunk : +--- branches
repos +--- trunk | +--- projA | +--- projB +--- branches +--- projA +--- projB
現在のtrunkからブランチRB-1.0を作成します
$ svn copy -m "Creating release branch for 1.0" \ svn://myhost/repos/trunk svn::/myhost/repos/branches/RB-1.0
手っ取り早いのは、新たにブランチを指定してチェックアウトする方法です。
現在trunkをチェックアウトして作業コピーを作っており、これをブランチRB-1.0に切り替える場合
誰かがリポジトリにコミットした際に自動である処理を実行したい、といった目的でフック機構が用意されています。
リポジトリの内容をあるディレクトリに展開しておき、リポジトリに新しいコミットが行われたらそのディレクトリを更新する処理をフック機構で自動で実行します。
リポジトリ file:///home/svn_rep/sample および、公開ディレクトリを /share/public/sample とします。
/home/svn_rep/sample/hooks ディレクトリに、実行権付きでpost-commit の名前で実行可能なファイルを作成します。
#!/bin/sh REPOS="$1" REV="$2" PUBLICDIR="/share/public/sample" LOGFILE="/tmp/svn_rep_sample_post_commit.log" export LANG=ja_JP.UTF-8 cd $PUBLICDIR svn update >> $LOGFILE 2>&1
/share/public/sample にあらかじめリポジトリ内容をチェックアウトし、しかるべきアクセス権を付けておきます。
~$ cd /share/public/sample sample$ svn co file:///home/svn_rep/sample sample$ chown -R svn:svn . sample$
svnserveでリポジトリを更新する場合、svnserve実行ユーザ権限でアクセス可能にしておきます。
ログファイルを/var/logの下に作成するとき、あらかじめアクセス権を付けておかないとエラーになるので、rootでファイルをtouchで作成し、ファイルのアクセス権を変更しておきます。
日本語のファイルがコミットされたとき、環境変数LANGで設定がないと、ファイル名をエンコードできずエラーとなります。
リポジトリにコミットがあったらメールで通知する処理をフック機構で自動実行します。
リポジトリが大きいときは、すべてのコミットの通知を受けたら大変なので、特定のディレクトリへのコミットを通知することまで実現を狙います。
(CollabNet Subversion serverで)リポジトリを作成すると、リポジトリディレクトリのhooksの下に、post-commit.tmplというファイルが出来ています。これを、post-commitの名前に変更し、実行権を付けます。
#!/bin/sh # POST-COMMIT HOOK # # The post-commit hook is invoked after a commit. Subversion runs # this hook by invoking a program (script, executable, binary, etc.) # named 'post-commit' (for which this file is a template) with the # following ordered arguments: # # [1] REPOS-PATH (the path to this repository) # [2] REV (the number of the revision just committed) :(中略) REPOS="$1" REV="$2" mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf
デフォルトでは、mailer.py スクリプトを呼び出していますが、これはSubversionのソースアーカイブに含まれているので、CollabNet Subversionバイナリを展開した中にはありません。
で、探してみたところ、日本語対策も入ったcommit-email-jp-CentOS5.pl なるスクリプトが以下サイトで公開されていました。
なお、このスクリプトは"-m <正規表現>"オプションで、メール通知する対象のディレクトリを正規表現で指定できるのですが、バグってます。Subversion Users MLに紹介されていた回避策として以下の修正をします。ただし、この修正をすると、必ず-mオプションの指定が必要になります。(絞り込みしない場合は、-m "." を指定)
-my @project_settings_list = (&new_project); +my @project_settings_list = ();
また、スクリプト中にメールサーバー名、svnlookコマンドのパスがハードコードされているので、使用環境に合わせて修正します。
-$smtp_server = "AAA.BBB.CCC.DDD"; +$smtp_server = "localhost";
-my $svnlook = "/usr/bin/svnlook"; +my $svnlook = "/opt/CollabNet_Subversion/bin/svnlook";
/home/svn_rep/sample がリポジトリ・ルートのディレクトリとして、上記サイトより入手した commit-email-jp-CentOS5.plをこのディレクトリ下のhooks下に保存します。
~$ pwd /home/svn_rep ~$ cd sample/hooks hooks$ cp /tmp/commit-email-jp-CentOS5.pl . hooks$
次に、hooksの中にpost-commitを作ります。まだ作っていなければ、post-commit.tmplを名前を変えて実行権を付けます。
hooks$ cp post-commit.tmpl post-commit hooks$ chmod +x post-commit hooks$
post-commitを編集します。commit-email-jp-CentOS5.plへの呼び出しを追記します。
/usr/bin/perl /home/svn_rep/sample/hooks/commit-email-jp-CentOS5.pl "$REPOS" "$REV" -m "." --from svn@examples.org -s '[Commit:sample]' scm@examples.org
注記:改行なしに記述します。
-s オプションは通知メールの題名に接頭辞として付く文字列です。通知先メールアドレスは複数列挙可能です。
備考
日本語のディレクトリ名は-mオプションの正規表現ではマッチしないようです。
Cygwinの場合、環境変数TERM にcygwinがセットされていますが、この場合viがうまく起動されず、以下のようなエラーとなります。TERM=vt100のように適切な値をセットします。
vi: cygwin: unknown terminal type svn: system('vi svn-commit.tmp') returned 1
bashで作業コピーを操作する際、ディレクトリ補完をするときに、.svnが各ディレクトリにできるため、ちょっと面倒です。シェル変数FIGNOREに.svnを登録していると、bashでの補完に.svnが対象外となるため操作が楽になります。
本来は新しいサーバから再チェックアウトが必要ですが、作業中のワークスペースをどうしても維持したい場合、各ディレクトリに生成される.svnディレクトリの中にあるentriesファイルの情報を修正することでごまかすことが出来そうです。
<?xml version="1.0" encoding="utf-8"?> <wc-entries xmlns="svn:"> <entry committed-rev="88" name="" committed-date="2006-01-23T12:34:56.789012Z" url="svn://oldhost/myrep/trunk" last-author="torutk" kind="dir" uuid="xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx" revision="88"/> <entry name="alpha" kind="dir"/> <entry name="beta" kind="dir"/> </ec-entries>
urlの部分を変更すれば、新しいホストに対応できそうです。
#!/bin/bash -f for e in $( find . -name "entries" ); do echo $e; cp $e $e.oldhost; sed -e 's/oldhost/newhost/g' $e.oldhost > $e; done
特定のファイルやディレクトリを、バージョン管理対象外としたい場合の設定手段は、意外と限られています。
未だバージョン管理下に置かれていないファイルおよびディレクトリを、svn status, svn add, svn importコマンドの対象から除外します。
逆に言えば、既にバージョン管理下に入ってしまったファイルやディレクトリを無視する設定はできません。また、addはできてしまいます。
バージョン管理ツールの真骨頂は差分情報の取得です。せっかく差分情報が保管されていても、差分情報を取り出し有効活用しなければ単なるファイル共有です。
作業コピーの上で
$ svn diff | awk '/^Index/ {print $NF}'
include/Sample.h src/Sample.cpp src/main.cpp $
とすると、ベースリビジョンと作業コピーとの比較で変更のあったファイルをリストアップします。
特定のレビジョン(例:123)と作業コピーとの比較は、svn diff -r 123 と、特定の2つのレビジョン間(例:100と123)の比較は、svn diff -r 100:123 と-rオプションで指定します。
作業コピーがない状態で、リポジトリの特定の2つのレビジョン間の比較(例:100と123)の比較は、レポジトリURLに@とレビジョン番号を指定して行います。
$ svn diff http://remote.example.com/repo/trunk/Hoge@100 http://remote.example.com/repo/trunk/Hoge@123 :
または、レポジトリが同一であれば
$ svn diff -r 100:123 http://remote.example.com/repo/trunk/Hoge :
svnのサブコマンドdiffのオプション-xに続けて指定するオプションで、空白や改行コードの違いを無視する・しないの制御が可能です。
空白文字の数が違っても差分として表示しない場合、
$ svn diff -x -b Hello.cpp
空白文字を差分比較で無視する場合
$ svn diff -x -w Hello.cpp
改行コードの違いを差分比較で無視する場合
$ svn diff -x --ignore-eol-stype Hello.cpp
上記複数を指定する場合、-xは1つだけ後にパラメータを指定できるので、
$ svn diff -x "-b --ignore-eol-stype" Hello.cpp
と-xのあとに""で囲んで複数オプションを指定します。
複数の会社で共同開発するソフトウェアの場合で、それぞれの会社の開発場所からSubversionサーバを共有できればいいのですが、往々にして共有できないことがあります。各会社でSubversionサーバを立て、担当するサブシステムをそこで開発し、ある程度の段階で全システムを統合する開発場所に持ってくるというシナリオになります。
このような場合、やってはいけない作業は次の流れです。
この場合、バージョン管理の禁じ手である、ファイルコピーが発生しています。考えられる問題は、
などが挙げられます。これではバージョン管理以前に逆戻りです。集中リポジトリ方式であるSubversionを、地理的に分散しているために無理やり分散リポジトリのような使い方をしているために生じています。
問題を回避するやり方のひとつに、ブランチの活用が考えられます。
なお、最後のマージ作業は、統合リポジトリの構成管理担当者がするべきです。
Windows用のSubversionソフトを探すと、現時点では、以下のソフトが見つかります。
CentOS 5では、Subversion 1.4.2が標準搭載されています。
Subversion 1.5をCentOS 5へインストールするメモはこちらです。
CollabNet Subversion 1.6をCentOS 5へインストールするメモはこちらです。
CentOS 4.4にインストールした際のメモです。
CentOSでは、パッケージ管理にyumを使用します。
# yum install subversion : #
しかし、2007年1月8日現在Subversionは1.4.2が最新版で、1.2を含めてそれより古い版はサポート外となっている状況にもかかわらず、yumでインストールされるSubversionは1.1.4となっています。そこで、RPM形式のバイナリパッケージをダウンロードしてインストールします。
Subversionの本家サイトから"Downloads"のリンクを辿ってBinary Packagesの"Red Hat 8.0, 9, Red Hat Enterprise Linux 3, 4"の項にある"UK Mirror"または"summersoft.fay.ar.us"のリンクを辿ります。rhel-4/i386のディレクトリ下にrpmパッケージがあります。
以下のrpmパッケージファイルをダウンロードします。
CentOS 4.4には、aprおよびapr-utilパッケージがインストールされていますが、バージョンがそれぞれ0.9.4-24.5.c4.2および0.9.4-21となっています。subversion-1.4.0-1が要求するaprおよびapr-utilのバージョンは0.9.7および0.9.7なので条件に合いません。そこで、先にaprとapr-utilの両パッケージをアップグレードします。
rpmコマンドのアップグレードは-Uオプションを指定します。
# rpm -Uvh apr-0.9.12-1.i386.rpm apr-util-0.9.12-1.i386.rpm : #
インストールを確認するには、rpmコマンドで-qオプションを指定します。
# rpm -q apr apr-0.9.12-1 # rpm -q apr-util apr-util-0.9.12-1 #
次に、subversionをrpmコマンドを使ってインストールします。インストール時は-iオプションを指定します。-vhオプションを追加すると、詳細情報の表示と進捗表示をrpmコマンドが行います。
# rpm -ivh subversion-1.4.0-1.i386.rpm : #
これでSubversionの基本機能が利用できるようになります。
svnserveをinet経由で起動する設定を行います。
/etc/services にsvnserveのサービス名・ポート番号登録をしますが、既に記述済みでした。
svn 3690/tcp # Subversion svn 3690/udp # Subversion
/etc/xinetd.d/svn ファイルを作成します。
service svn { disable = no socket_type = stream protocol = tcp wait = no user = apache server = /usr/bin/svnserve server_args = -i -r /home/svn/repos }
user=で指定したユーザ権限でsvnserveがファイルを読み書きするので、リポジトリに指定したディレクトリ以下は指定したユーザ権限でファイルの読み書きができるようにパーミッションを設定しておく必要があります。
# cd /home/svn # chown -R apache repos
svnを登録
# /sbin/chkconfig --add svn # /sbin/chkconfig --list | grep svn svn: on #
xinetdを再起動
# /etc/rc.d/init.d/xinetd restart xinetd を停止中: [ OK ] xinetd を起動中: [ OK ] #
Linuxで使えるGUIのSubversionツール
外部diff/mergeツールには、
svn diffなどのコマンドは通常CUI上にdiffツールの出力結果をテキスト表示します。しかし、Windows環境でのGUIによる視覚的なdiffツール(WinMergeなど)に慣れてしまうと、やっぱり不便を感じます。そこで、svnコマンドから比較結果を外部ツールに出すように設定を行います。
ユーザ毎に設定する場合、~/.subversion/configファイルに外部diffツールの設定を記述します。ただし、ツールによってコマンドライン引数の指定が異なるので、通常はsvnコマンドからシェルスクリプトを呼び出し、シェルスクリプト内にコマンドライン引数を使用する外部ツールに合わせて置き換える記述を行います。
~/.subversion/configファイルを編集
[helpers] diff-cmd = /home/torutk/bin/svn-diff-meld diff3-cmd = /home/torutk/bin/svn-diff3-meld diff3-has-program-arg = false
~/bin/svn-diff-meldファイルを作成
#!/bin/sh # SVN diff wrapper for meld left="$6" right="$7" meld "$left" "$right"
~/bin/svn-diff3-meldファイルを作成
#!/bin/sh # SVN diff3 wrapper for meld mine="$9" older="$10" yours="$11" meld "$mine" "$older" "$yours"