satoshiabe.jp : Introduction to Subversion
HOME > DOCUMENTS > Subversion > Introduction to Subversion
まえがき
このドキュメントは、「これから Subversion をインストールしてバージョン管理しようとしている人」を想定している。 より詳細な情報については、公式ドキュメントなどを参照されたし。
Subversion とは
Subversion は、バージョン管理システムである。 有名なソフトウェアとしては CVS を挙げることができる。 Subversion は CVS をもとに開発されたソフトウェアだ。 これからバージョン管理システムの導入を検討している場合、Subversion は十分に魅力的な選択肢になるだろう。
このページの解説は、最初に、サーバとクライアントを同一マシンと想定して説明する。 ページの下のほうで、リモートクライアントからの接続とアクセス制限について簡単に説明する。 サーバ、クライアントともに Windows 版が存在するようだが、Windows プラットフォームについての説明をしない。 なお、Windows プラットフォームで Subversion クライアントを使用したことがあるが、update コマンドを実行すると大量に I/O が発生し、その後の動作が重くなるので、快適に使用できたためしがない。
Subversion をインストールする
それでは、Subversion をインストールしてみよう。 使用しているディストリビューションにより、インストール方法が異なる。 Red Hat 系 GNU/Linux を使用している場合、rpm コマンド、あるいは yum や apt を使用してインストールすれば楽だと思う。 私は、RPM パッケージをインストールできるディストリビューションの場合、ソースパッケージからのインストールだけを経験している。
Debian GNU/Linux の場合、以下のとおりだ。
$ su - # apt-get update # apt-get install subversion
Ubuntu Linux の場合、sudo コマンドを実行する。
$ sudo apt-get update $ sudo apt-get install subversion
FreeBSD の場合、以下を実行するか
% su - # pkg_add ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages/devel/subversion-x.x.x.tbz
あるいは
% su - # cvsup -g /etc/ports-supfile # cd /usr/ports/devel/subversion # make install clean
あるいは以下のように Subversion をインストールする。
% su - # cvsup -g /etc/ports-supfile && portsdb -Uu && portinstall subversion
ソースからインストールする場合、普通に作業する。 これは FreeBSD 以外にインストールする場合でも同じだろう。
% wget http://subversion.tigris.org/downloads/subversion-x.x.x.tar.gz % tar xzvf subversion-x.x.x.tar.gz % cd subversion-x.x.x % ./configure % make % su # make install clean
./configure --prefix=/usr/local/svn など指定した場合、.bash_profile ファイルなどに path を追記すること。 設定例を示す。 source コマンドで PATH に設定した値をカレントシェルで有効する。
% cat << EOF >> ~/.bash_profile export PATH="/usr/local/svn/bin:$PATH" EOF % % source ~/.bash_profile
リポジトリを作成する
リポジトリを作成する。 リポジトリとは、Subversion がバージョン管理している情報を保存する場所(ディレクトリ)だ。
まず、リポジトリを格納するディレクトリを作成する。 自分のみが Subversion を使用する場合、ホームディレクトリのどこかで十分んだろう。
% mkdir /home/you/repos
svnadmin コマンドを実行し、リポジトリを作成する。
svnadmin create path
引数に指定したディレクトリにいくつかのファイルが作成される。
% svnadmin create /home/you/repos % % ls -1F /home/you/repos conf/ dav/ db/ format hooks/ locks/ README.txt
プロジェクトを登録する
プロジェクトを登録してみる。 ここで「プロジェクト」とは、Subversion の管理下にないファイルのことを意味している。 このプロジェクトを Subversion に登録し、今後、バージョン管理をしていくことになる。 svn コマンドに improt オプションを指定して実行する。 これにより、Subversion がファイル群のバージョンを管理するようになる。 -m オプションを指定することにより、続く引数をメッセージとして処理する。
svn import [path] URL
非常にオーソドックスなディレクトリの構成は以下のとおり。 trunk ディレクトリに、program.c ファイルが保存されていると仮定する。
/home/you/my_project/ |---branches/ |---tags/ |---trunk/ |---program.c
リポジトリのアクセス方法はいくつか種類がある。 今回はローカルディスク上にリポジトリが存在するため、file: を指定する。 file: を指定する場合 / を 3 つ指定するので注意すること。
- URL
- 詳細
- file:///
- リポジトリがローカルのディスク上に存在する場合
- http://
- リポジトリが Apache HTTP Server により公開され WebDAV プロトコルでアクセスする場合
- https://
- リポジトリが Apache HTTP Server により公開され WebDAV プロトコルかつ SSL でアクセスする場合
- svn://
- リポジトリが Subversion により公開され独自の TCP/IP プロトコルでアクセスする場合
- svn+ssh://
- リポジトリが Subversion により公開され SSH かつ独自の TCP/IP プロトコルでアクセスする場合
% svn import -m "Importing my project" /home/you/my_project file:///home/you/repos 追加しています /home/you/my_project/branches 追加しています /home/you/my_project/tags 追加しています /home/you/my_project/trunk 追加しています /home/you/my_project/trunk/program.c リビジョン 1 をコミットしました。 %
リビジョンとは、Subversion が管理しているリポジトリのバージョン番号だ。 上の例において、最初の import でリビジョンが 1 になっている。 今後、コミットするたびにリビジョン番号がひとつずつカウントアップされていく。
チェックアウトする
作業を始めるまえに、必ずチェックアウトすること。 チェックアウトとは、ローカルに作業コピーを作成することを意味する。
svn checkout URL [path]
以下では作業コピーの保存ディレクトリを /home/you/work としている。
% svn checkout file:///home/you/repos/ /home/you/work A /home/you/work/branches A /home/you/work/tags A /home/you/work/trunk/program.c リビジョン 1 をチェックアウトしました。 %
チェックアウトすると、.svn というディレクトリが作成される。 . から始まるファイル名であるため -a オプションで ls を実行すると確認できる。 このディレクトリは非常に重要なディレクトリであるため、決して削除しないこと。 放置しておけば良い。 尚、この .svn ディレクトリには、BASE リビジョンと呼ばれる、リポジトリに存在する各ファイルが保存されている。
ファイルを追加する
ローカルで新しくファイルを作成した場合、svn コマンドに add オプションを指定して実行する。
svn add path
add オプションを指定することで、追加予告をすることになる。 リポジトリに反映されるのは、次回、コミットしたとき。
% svn add README.txt
ファイルを削除する
削除予告をする。
svn delete path svn delete URL
指定したファイルは、ローカルの作業コピーから直ちに削除される。 ただし、リポジトリに反映されるのは、次回、コミットしたとき。
% svn delete trash.txt
ファイルを移動する
作業コピー、あるいはリポジトリのファイルを移動する。
svn move source target
source と target は、「作業コピー同士」か「リポジトリ URL 同士」をサポートしている。 作業コピーに対して svn move を実行した場合、リポジトリに反映されるのは、次回、コミットしたとき。
% svn move text.old text.new
ディレクトリを作成する
指定した path あるいは URL にディレクトリを作成する。
svn mkdir path svn mkdir URL
new_directory ディレクトリを作成する例。
% svn mkdir new_directory
ファイルを最新の状態に更新する
チェックアウトしてから時間が経ったら、作業コピーをリポジトリに登録されている状態と同期させるために、svn update コマンドを実行しよう。
svn update path
自分ひとりで Subversion を使用している場合、このコマンドを実行することはないかもしれない。
% svn update
変更を取り消す
ファイルやディレクトリの変更を取り消す。 予告した作業も取り消せる。
svn revert path
使用例をひとつ。
% svn add hoge.txt % % svn status A hoge.txt % % svn revert hoge.txt Reverted hoge.txt % % svn status ? hoge.txt
--recursive オプションを指定し、続く引数にディレクトリを指定すると、そのディレクトリ以下の変更をすべて取り消せる。
% svn revert --recursive .
ステータスを確認する
作業コピーを保存しているローカルの最上位階層で svn status コマンドを実行してみよう。 すると、各ファイルの状態を確認できるはずだ。
svn status [path]
- A
- 追加予約されたファイル
- D
- 削除予約されたファイル
- M
- 修正されたファイル
- !
- svn コマンドを使用せずファイルを削除したり移動した場合など。
- ?
- バージョン管理されていないファイル
% svn status A README.txt M program.c
コミットする
ローカルのファイル群をリポジトリに反映する。 svn commit コマンドを実行する。
svn status [path]
path を指定しない場合、カレントディレクトリ . が対象となる。
% svn commit -m "Updated all files"
ファイルを指定して svn commit すると、そのファイルだけがコミットされる。
% svn commit -m "Updated all files" README.txt
-F オプションを指定することで、-m "message" を代替できる。 file には、メッセージを事前に記述しておくこと。
% cat file Updated all files!!! % svn commit -F file
今後の作業の流れ
これ以降は、基本的に以下の順序で繰り返し作業すれば良い。 チェックアウトを既に実行済みであるため、改めて実行しなくてよい。
1. svn update
svn update コマンドでローカルディスク上のファイルを最新の状態に更新する。
2. 作業
既存のファイルを修正したり、ファイルを追加、あるいは削除したり、作業する。
3. svn status
svn status コマンドで各ファイルの状態を把握する。
4. コミットする
svn commit コマンドでプロジェクトの内容をリポジトリに反映する。
1 に戻る。
他 : ログを確認する
svn コマンドに log オプションを指定すると、ログメッセージを表示できる。 -r でリビジョンを指定して実行できる。 リビジョンを指定しない場合、これまでのログがすべて表示される。
svn log [path]
% svn update リビジョン 168 です。 % svn log -r 168 ------------------------------------------------------------------------ r168 | satoshi | 2006-03-27 20:16:45 +0900 (月, 27 3 2006) | 1 line Updated comp.html ------------------------------------------------------------------------ %
補足 : リモートクライアントから Subversion を利用できるように設定する
サーバで実行されている Subversion をリモートクライアントが利用できるよう、サーバの設定をしてみる。 サーバは、クライアントからの接続を xinetd で制御する。
今回は、Red Hat Linux 7.3 と FreeBSD 6.0 サーバを設定する例を説明している。
順序が逆になるが、サーバの設定を完了した後、リモートクライアントは、以下のようにサーバに接続してチェックアウトを実行する。
$ mkdir work $ cd work/ $ svn checkout svn://remote_host/
ちなみに、サーバが xinetd を使用せず、デーモンで Subversion を起動する場合、以下のコマンドを実行する。
# svnserve -d -r /home/svn/repos
Red hat Linux 7.3 編
Red Hat Linux 7.3 のような古い distribution を使用しているときなど、/etc/services ファイルに Subversion 用のエントリが存在しない場合がある。 存在しない場合、追記しておく。 存在する場合、そのままで構わない。
% su - # vi /etc/services ### 以下の 2 行を追記する svn 3690/tcp # Subversion svn 3690/udp # Subversion :wq
xinetd がインストールされていない場合、インストールしておく。 以下は、どこからともなく入手した rpm パッケージをインストールする例。 インストールされているかどうか不明な場合、rpm -aq | grep 'xinetd' などを実行し、Subversion の有無を確認すること。
$ su - # rpm -ivh xinetd-x.x.x.i386.rpm
まずは xinetd 本体の設定設定ファイル /etc/xinetd.conf を作成する。
# vi /etc/xinetd.conf defaults { instances = 60 log_type = SYSLOG authpriv log_on_success = HOST PID log_on_failuer = HOST } includedir /etc/xinetd.d :wq
Subversion 用の設定ファイル /etc/xinetd.d/svn ファイルを作成する。
# vi /etc/xinetd.d/svn service svn { disable = no socket_type = stream protocol = tcp wait = no user = svn server = /usr/local/svn/bin/svnserve server_args = -i -r /home/you/repos } :wq
server_args の補足
-i : inetd または xinetd 経由で起動する -r : 指定したディレクトリ以下をリポジトリとして公開する
xinetd デーモンを起動する。 事前に /var/log/messages を tail しておくこと。
# /etc/rc.d/init.d/xinetd start
FreeBSD 6.0 編
FreeBSD の場合、デフォルトで xinetd がインストールされていないはずなであるため、xinetd をインストールしてから設定する。 また、起動時に自動的に起動するよう設定する。
$ su - # pkg_add -r xinetd # ### 自動起動のための設定 # vi /etc/rc.conf xinetd_enable=YES :wq
設定ファイルは /usr/local/etc/xinetd.conf を作成する。
# vi /usr/local/etc/xinetd.conf defaults { instances = 60 log_type = FILE /var/log/xinetd.log log_on_success = HOST PID log_on_failuer = HOST } includedir /usr/local/etc/xinetd.d
/usr/local/etc/xinetd.d/svn ファイルを作成する。 まず、ディレクトリを作成しておくこと。
# mkdir /usr/local/etc/xinetd.d # # vi /usr/local/etc/xinetd.d/svn service svn { disable = no socket_type = stream protocol = tcp wait = no user = root server = /usr/local/bin/svnserve server_args = -i -r /home/you/repos } :wq
server_args の補足
-i : inetd または xinetd 経由で起動する -r : 指定したディレクトリ以下をリポジトリとして公開する
xinetd デーモンを起動する。 事前に /etc/xinetd.conf で指定した /var/log/xinetd.log を tail しておくこと。
# /usr/local/etc/rc.d/xinetd.sh start
補足 : リモートクライアントからのアクセスを制御する
Subversion をリモートクライアントから利用できるように設定し、認証機能を有効にする。
作業対象は以下のファイル 2 つだ。 リポジトリのディレクトリに conf というディレクトリが存在する。 その conf ディレクトリに存在する passwd ファイルと svnserve.conf ファイルだ。
% ls /home/you/repos/conf/ passwd svnserve.conf %
リポジトリが保存されているディレクトリへ移動する。
% cd /home/you/repos/conf/
念のため設定ファイルの svnserve.conf をバックアップする。
% cp svnserve.conf svnserve.conf.bk
svnserve.conf を編集する。 anon-access を none に変更することにより、匿名ユーザは何もできなくなる。
% vi svnserve.conf # [general] ### コメントアウトを解除する [general] # anon-access = read ### コメントアウトを解除し none に変更 anon-access = none # auth-access = write ### コメントアウトを解除する auth-access = write # password-db = passwd ### コメントアウトを解除する password-db = passwd # realm = My First Repository ### コメントアウトを解除し文字列を変更 realm = My Repository vi を終了する :wq
認証用のファイル passwd を編集する。
こちらも、念のためバックアップファイルを作成する。
% cp passwd passwd.bk
ファイルを編集する。
% vi passwd ### This file is an example password file for svnserve. ### Its format is similar to that of svnserve.conf. As shown in the ### example below it contains one section labelled [users]. ### The name and password for each user follow, one account per line. # [users] ### コメントアウトを解除する [users] ### エントリを追加する ### 形式は username = passwd # harry = harryssecret # sally = sallyssecret satoshi = password
クライアントから接続して試してみる。
% svn checkout svn://remote_server/
補足 : リポジトリをバックアップする (1)
おそらくバージョン管理システムを使用しだすと、それがないなんて考えられなくなるだろう。 つまり、自分(たち)にとって、非常に重要なツールであり、かつ、重要なデータが蓄積されていくことになる。 何か起きてしまう前に、リポジトリをバックアップしよう。
shell スクリプトを cron で実行する
簡単だが、注意点もある、あまりスマートではないバックアップ方法を紹介する。 具体的には、リポジトリのディレクトリを tar でかためる処理をスクリプトにして、それを cron で定期的に実行する方法だ。 問題点として、tar でアーカイブしている最中にリポジトリの内容が変更されると不正なデータを生成してしまう。 この方法を採用してバックアップする場合、確実に誰も使用していない時間帯に実行しなければならない。 たとえば、誰も使用していない深夜など。
サンプルのスクリプトを shell で作成した。 十分な試験をしていないので、このスクリプトをそのまま使用するときは必ず試験すること。
スクリプトは、リポジトリのディレクトリを tar でかためて別のディレクトリに保存している。 せめて、別のパーティションに、できるなら、物理的に別のディスクに保存しよう。 別の機会に、リモートのマシンへ転送するスクリプトを紹介する。
リポジトリのディレクトリは /home/you/repos だ。 このディレクトリを tar でかためて、ファイルを /home/you/backup ディレクトリに保存する。 バックアップのファイルはたまっていく一方なので、そのうちディスクを圧迫しかねない。 そのため、最新の 10 ファイルだけを保存することにする。
難しくないと思うが、スクリプトのポイントを簡単に説明しておく。 まず、コマンド置換を使用し、date コマンドの結果を tar で作成するファイル名 $target_file に格納している。 算術式展開で、残したいファイル数 10 との差分を $rm_file_num に格納している。 差分が 0 より大きい場合、for 文で必要な回数だけループし、ファイルを削除している。
#!/bin/sh ### 各変数を定義する target_dir=/home/you backup_dir=/home/you/backup repos_name=repos target_file="repos-`date +%Y-%m-%d`.tar.gz" backup_file_num=10 ### tar でリポジトリをかためる cd $target_dir tar czf $target_file $repos_name && mv $target_file $backup_dir cd $backup_dir ### バックアップされているファイル数を $count に格納する count=`ls | grep -c '^repos-'` ### $count - $backup_file_num の結果を $rm_file_num に格納する rm_file_num=$(($count - $backup_file_num)) ### $rm_file_num が 0 以下の整数なら exit コマンドを実行してスクリプトを終了する if [ $rm_file_num -le 0 ] ; then exit fi num=0 for i in `ls repos-*` ; do rm $i num=$(($num + 1)) if [ $num -eq $rm_file_num ] ; then exit fi done
このスクリプトを cron に登録して実行する crontab コマンドで、毎日 3 AM に指定する例。
% crontab -e 0 3 * * * $HOME/bin/daily.job :wq
FTP でリモートホストにバックアップファイルを転送する
先ほど説明したバックアップファイルを処理する shell スクリプトに組み込める、ファイルを FTP でリモートホストに転送する機能を紹介する。
まず、FTP でリモートホストに転送するため、以下の変数を定義する。 実際にスクリプトに組み込む際には、変数定義をスクリプトの最上位(他の変数を定義している部分)で一緒に定義した方が見やすいだろう。
remotehost : リモートホストのホスト名 or IP address
username : ftp で認証に使用するアカウント
userpassword : ftp で認証に使用するパスワード
remote_dir : リモートホスト上のファイルを put するディレクトリ
続いて cd コマンドを実行し、$backup_dir に移動している。 $backup_file が存在しているかどうかを if 文で確認し true なら ftp コマンドでファイルを転送する。 ヒアドキュメントの中で $username と $userpassword が変数展開され、認証を通過する。 $remote_dir に cd して $backup_file を put している。
remote_host='192.168.0.100' username=svn userpassword=svn remote_dir=backup cd ${backup_dir} if [ -f ${backup_file} ] ; then ftp -n -d -v ${remote_host} << _EOD user ${username} ${userpassword} passiv cd ${remote_dir} binary put ${backup_file} bye _EOD else echo "EROOR : ${backup_file} NOT exists. " exit 1 fi
このモジュールを、もとのスクリプトの tar コマンドが実行された後あたりに加える。 すると、tar コマンドが終了した後に、リモートホストにファイルが転送される。 尚、忘れずにリモートホスト側にアカウントとディレクトリを作成すること。
ちなみに、FTP 機能を実装したスクリプトを実行していると、リモートホスト側にファイルがたまりはじまる。 そのため、リモートホスト側でも、一定期間を過ぎた古いバックアップファイルを削除するスクリプトを作成しなければならないだろう。
補足 : リポジトリをバックアップする (2)
続いて、ややスマートなバックアップも追記しておく。
svnadmin コマンドに dump オプションを指定し、リポジトリのダンプを生成する。 ファイル名を date コマンドなどを使用してユニークにしておき、cron などで定期的にダンプしておくとよいだろう。
$ svnadmin dump $REPOS_HOME > ./repos.dump
リストアする。 svnadmin コマンドに load オプションと、リポジトリにディレクトリを指定し、リダイレクトでダンプファイルを指定して、実行する。
### リポジトリ用のディレクトリを作成 $ mkdir ./svn $ ### リポジトリを生成 $ svnadmin create ./svn/repos $ ### リストア $ svnadmin load ./svn/repos < ./repos.dump $ ### 必要ならオーナーとグループを設定 $ chown -R me:me ./svn/repos
おわり。
リンク
Subversion に関連する Web サイトと、有益な情報を得られる Web サイトにリンクを作成しておく。
subversion.tigris.org (tigris.org)
Subversion によるバージョン管理 (bluegate.org)
@IT:Subversion によるバージョン管理 (1/3) (atmarkit.co.jp)
Manpage of SERVICES (linux.or.jp)
The services and protocols Files (tldp.org)
xinetd (xinetd.org)