CVSに代わる次世代バージョン管理システムSubversion。1.0がリリースされたということで使ってみました。ただし、インストールぐらいまでしかまだ書き切れてません。
参考リンク集
- 本家
- Subversionによるバージョン管理(日本語訳)
- Subversionで管理せよ - 鵜飼さんのUNIX USER 2003年8月号の原稿
- Subversion-wiki - 微量ながら、リポジトリの管理でのよくありそうな疑問のQ&Aがまとまっています。
はじめに
バージョン管理システムとは何ぞや? ということは説明するまでもないと思いますが、一応。バージョン管理システムとは文字通り、「あるもの」の変更を管理することです。あるものとは、ソフトウェア開発だったらソースコードだったり、ドキュメントなどでしょう。メジャーなものではCVSやVSSがありますが、SubversionはCVSに取って代わることを目的に開発されています。CVSとの一番の違いは、CVSがファイル単位でバージョンを管理するのに対し、Subversionはディレクトリツリー単位でバージョンを管理します。つまり、CVSではファイル名の変更などは履歴が保持されませんが、Subversionはこのファイルの移動に関しても履歴を保持することが可能となっています。
インストール
# apt-get install subversion subversion-tools
リポジトリの作成
リポジトリのディレクトリ/var/local/subversion/reposを用意し、グループusersからフルアクセスできるようにします。なお、リポジトリのパスは以降$svnreposと表現します。
# mkdir -p /var/local/subversion/repos # chgrp users /var/local/subversion/repos # chmod 775 /var/local/subversion/repos
(以降、usersグループのユーザで作業)リポジトリを作成します。
$ umask 002 $ svnadmin create $svnrepos $ ls $svnrepos README.txt conf dav db format hooks locks
プロジェクトのimport
myfilesという仮のプロジェクトを作成します。
$ mkdir -p ~/tmp/myfiles $ cd ~/tmp/myfiles
必要なディレクトリを作成します。(慣習的に下記の3ディレクトリを作るようです)
$ mkdir {trunk,branches,tags}
適当にファイルを作成します。(バージョン管理するファイルはtrunk以下に作成することに注意)
$ echo "This is a test." > trunk/test.txt
ではmyfilesプロジェクトのファイルをimportしてみましょう。
$ svn import ~/tmp/myfiles file:///$svnrepos -m "initial import" Adding /home/kazuhiro/tmp/myfiles/trunk Adding /home/kazuhiro/tmp/myfiles/trunk/test.txt Adding /home/kazuhiro/tmp/myfiles/branches Adding /home/kazuhiro/tmp/myfiles/tags Committed revision 1.
これでリポジトリにmyfilesプロジェクトのディレクトリツリーが反映されました。今度は、リポジトリのツリーをcheckoutしてローカルの作業コピーを取得します。
$ cd ~/tmp $ rm -rf myfiles $ svn checkout file:///$svnrepos/trunk myfiles A myfile/trunk A myfile/trunk/test.txt A myfile/branches A myfile/tags Checked out revision 1.
クライアント/サーバ方式でのアクセス
Subversionではいわゆるクライアント/サーバ方式によってネットワーク上のリポジトリにアクセスすることが可能です。代表的な手段として、
- subversionパッケージに付属のsvnserveを使用する
- Apache2でWebDAV/DeltaVプロトコルを使用する
があります。これらのやり方を詳しく見ていきましょう。
svnserveを使用する(with xinetd)
subversionパッケージに含まれる、svnserveというデーモンを使用します。ここではxinetd経由で使用してみます。まず、前提として/etc/servicesに下記の行が存在しているか確認してください。
$ grep svn /etc/services svnserve 3690/tcp svn subversion # Subversion protocol svnserve 3690/udp svn subversion
確認できたら[1]、rootになって/etc/xinetd.d/以下にsvnserveという名前のファイルを作成します。その中身は下記のようになります。
# default: on
# svnserve configuration
service svnserve
{
disable = no
protocol = tcp
socket_type = stream
user = www-data
group = www-data
wait = no
server = /usr/bin/svnserve
server_args = -i -r /var/local/subversion
log_on_success += DURATION HOST USERID
log_on_failure += HOST USERID
}
注意点としては、svnserveを動かすユーザ(とグループ)をwww-dataにしていることです。これは、後述のApache2経由でアクセスする場合のことを考慮してこうしています。というのは、デーモンを実行しているユーザがリポジトリへの読み書きの権限がないと、リポジトリへのアクセスが出来ないという問題があり(当たり前ですが)、これを運用上どう回避していくか、という課題があります。ここでは、Apache2とsvnserveの両方からリポジトリにアクセスできるようにしたいので、www-dataでsvnserveも動かしてしまう、という方法を取っています。おそらく一番簡単なのは、リポジトリをどのユーザからも読み書き出来るようにしてしまうことだと思いますが、それは何となく気が引けるのでやめました。
というわけで、現在のリポジトリのオーナーをwww-dataに変更します。
# chown -R www-data:www-data $svnrepos
さらに、TCPWrapperを使用している場合は、/etc/hosts.allowにて他のマシンがsvnserveにアクセスできるようにします。(ここでは、自分自身とLAN内のマシンからアクセスできるようにしています)
svnserve: 192.168.1. 127.0.0.1
それでは、xinetdをreloadしてみましょう。
# /etc/init.d/xinetd reload
そして、クライアントマシンからリポジトリにアクセスできるか確認してみます。
$ svn co svn://ホスト名/repos myfiles A myfile/trunk A myfile/trunk/test.txt A myfile/branches A myfile/tags Checked out revision 1.
リポジトリへの書き込み
svnserveで動かす場合、特に何も設定しないとリポジトリが読み取り専用になります。よって、変更をコミットしようとした場合
svn: Commit failed (details follow): svn: Connection is read-only
というエラーになります。これを回避するには「認証済みのユーザである」ことをsvnserveに対して知らせなければなりません。これはsvnserve.confの修正とパスワードファイルを用意することで実現できます。まず、$svnrepos/confディレクトリ以下にsvnserve.confというファイルがあるので、これの"[general]"と"password-db = passwd"の行をコメントアウトします[2]。そして、svnserve.confと同じ階層にpasswd[3]というファイルを作って、以下のようにリポジトリへの書き込みを許すユーザとパスワードを書いておきます。
[users] # USERNAME = PASSWORD foobar = hoge
これでコミットしようとした時に認証が始まるようになります。ちなみに、認証していない段階でコミットが出来ないのは、svnserve.confのanon-access がデフォルトではreadになっているからです。これをwriteにすれば、認証していなくてもいきなりコミットすることが出来ます。
Apache2でWebDAV/DeltaVプロトコルを使用する
まず、前提としてApache2が必要になります。インストールしていない場合はapache2のページを参考にしてインストールしてください。また、Apache2にロードさせるmod_dav_svnというモジュールが必要になるので、apt-getでインストールしておきます[4]。
# apt-get install libapache2-svn
Apache2の設定であるhttpd.conf(もしくは相当のもの)を修正します。具体的には下記の行を追加し、mod_davとmod_dav_svnモジュールを組み込む必要があります。
LoadModule dav_module modules/mod_dav.so LoadModule dav_svn_module modules/mod_dav_svn.so
Debianならa2enmodを使用すれば良いでしょう。httpd.confにレポジトリの場所などを伝える設定を追加します。
<Location /svn>
DAV svn
SVNPath /var/local/subversion/repos # リポジトリへの絶対パス
</Location>
これで、http://サーバ名/svnというURLはmod_dav_svnモジュールによって処理されます。この他に、パスワード認証を付けてアクセスを制限したい場合は、下記のようにします。
<Location /svn>
DAV svn
SVNPath /var/local/subversion/repos # リポジトリへの絶対パス
# Basic認証を有効にする場合
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /etc/apache2/dav_svn.passwd
# 認証されていないユーザでも参照は可能にする
<LimitExcept GET PROPFIND OPTIONS REPORT>
Require valid-user
</LimitExcept>
</Location>
そして、AuthUserFileで指定したパスワードを格納するファイルを作成します。
# htpasswd2 -c /etc/apache2/dav_svn.passwd
以上で設定は完了です。Apache2を再起動します。
# /etc/init.d/apache2 force-reload
では、リポジトリにHTTP経由でアクセスしてみましょう。先程のmyfilesプロジェクトのファイルをチェックアウトしてみましょう。
$ svn co http://サーバ名/svn myfiles A myfile/trunk A myfile/trunk/test.txt A myfile/branches A myfile/tags Checked out revision 1.
と返ってくれば成功です。
日常の作業
ドキュメントには、実にたくさんのことが書かれていますが、実際日々の作業で使うのは以下のコマンドぐらいです。
| checkout(co) | プロジェクトのチェックアウト |
| update(up) | 作業コピーの更新 |
| add | ファイル/ディレクトリの追加 |
| mkdir | ディレクトリの作成 |
| move | ファイル/ディレクトリの移動 |
| copy(cp) | ファイル/ディレクトリのコピー |
| delete(del remove rm) | ファイル/ディレクトリの削除 |
| commit(ci) | 変更の反映 |
| status | 作業コピーの状態を表示 |
| diff | 2つのファイルの差分を表示 |
| log | コミットログメッセージの表示 |
まずはプロジェクトをcheckout
一番初めに、作業コピーをリポジトリから取得する必要があります。作業コピーがないと何も出来ませんから。
$ svn checkout URL... [PATH]
URLは複数指定することが出来ますが、一般的には1つだけでしょう。PATHを指定しなかった場合はURLで指定したリポジトリの末尾のディレクトリが適用されます。例えば、リポジトリのURLがhttp://foo.org/reposで、作業コピーをworkディレクトリとしてチェックアウトしたい場合は下記のようにします。
$ svn co http://foo.org/repos work A work/trunk (略) Checked out revision 1.
作業コピーの更新
プログラム開発の現場では、大抵プロジェクトメンバーによって日々リポジトリのファイルが新しくなっていきます。そのため、自分の作業コピーを最新にして他の人の変更を取り込むことが必要になってきます。
$ svn up
と打つことで、その時点でのリポジトリの内容が自分の作業コピーに反映されます。リポジトリと作業コピーの間に差異があった場合は、下記のようにその情報が出力されます。
A dir/trunk/a.c A dir/trunk/b.c
右のものはファイル/ディレクトリ名だとわかりますが、左のものはなんでしょうか。これは、作業コピーに対してどのような修正が行われたかを表すものです。
| A | 追加 |
| D | 削除 |
| U | 更新 |
| C | 衝突 |
| G | マージ |
ファイル/ディレクトリの追加
$ svn add PATH...
PATHには追加するファイル/ディレクトリを指定します。複数指定可能です。作業コピーにhello.cというファイルを追加したい場合は下記のようにします。
$ svn add hello.c
ディレクトリを追加する場合、そのディレクトリの中身も再帰的に追加されます。たとえば、libディレクトリをローカルに作成していたとして、その中にprintf.cがある場合、
$ svn add lib
と打つと、
A lib A lib/printf.c
となります。mkdirを使用してディレクトリを追加することも出来ますが、addはその中身も含めて追加出来るので便利です。addを実行しその変更が問題なければ、addの変更を反映するためにcommitする必要があります。