トップ 差分 一覧 ソース 検索 ヘルプ PDF RSS ログイン

subversion

[server] [linux]

CVSに代わる次世代バージョン管理システムSubversion。1.0がリリースされたということで使ってみました。ただし、インストールぐらいまでしかまだ書き切れてません。

参考リンク集

はじめに

バージョン管理システムとは何ぞや? ということは説明するまでもないと思いますが、一応。バージョン管理システムとは文字通り、「あるもの」の変更を管理することです。あるものとは、ソフトウェア開発だったらソースコードだったり、ドキュメントなどでしょう。メジャーなものでは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 マージ
Cの衝突以外はその通りに受け取れば良いでしょう。しかし、衝突は「誰かがリポジトリに対して行った修正と自分の作業コピーに対する修正が衝突している」ことを表しています。つまり、誰かが行った修正も含めてあなたの修正をコミットしなければなりません。

 ファイル/ディレクトリの追加

$ 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する必要があります。

  • [1]ない場合は追加してください
  • [2]anon-accessの行はコメントアウトしなくても構いません
  • [3]password-dbで指定したファイル名
  • [4]Debian以外でのインストール方法は割愛します