[ Topページへ戻る ]

Subversionでバージョン管理

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/
    $
プロジェクトディレクトリの下にtrunk/tags/branchesを設けている場合
$ 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の場合、競合が発生すると、以下のファイルが生成されます。

aFile
コンフリクトが発生した個所にその状況が挿入されたファイル
aFile.mine
作業コピーをupdateする前のファイルは、これにリネームされる
aFile.rXXXX (XXXXはupdate前の作業ファイルのチェックアウトされた時の内容)
update前の作業コピーが紐付けされているリポジトリの内容
aFile.rXXXX (XXXXはupdate後のリポジトリの内容)
updateによって最新となるリポジトリの内容

作業コピーのファイルやディレクトリを新たにリポジトリに登録するには

    $ svn add Greeting.java
    A    Greeting.java
    $ svn commit Greeting.java

commit前に取り消しする場合は、svn revertを使用します。

作業コピーのファイルやディレクトリの情報を見るには

    $ svn info Greeting.java

作業コピーのファイルやディレクトリの変更状況を確認するには

    $ svn status
    MM    Greeting.java

リポジトリの新規作成

バークレイDB
    $ svnadmin create /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から共有すると不整合が発生します。

ファイルシステム
    $ 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ファイルは含まれないので、設定ファイルは手動でバックアップを取る必要があります。

リポジトリへのimport

以下のディレクトリをSubversion管理下に置きたい場合
    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
例えば、LastChangedRevisionを有効にするには
    $ 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の置換が有効になります。

ネットワークからアクセスするには

HTTP(HTTPS)の場合

 WebDAV/deltaVプロトコルで通信する(HTTP1.1の拡張)
 必要なもの:Apache httpd 2.0、mod_DAV、Subversion、mod_dav_svn

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つ方法があり、良いと思う方を使えばよいようです。

各プロジェクト毎にtrunk/branchesを設ける方法
repos
   +--- projA
   |       +--- trunk
   |       +--- branches
   +--- projB
   :       +--- trunk
   :       +--- branches
リポジトリのトップで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からブランチに切り替える

手っ取り早いのは、新たにブランチを指定してチェックアウトする方法です。

現在trunkをチェックアウトして作業コピーを作っており、これをブランチRB-1.0に切り替える場合

フック(自動処理)

誰かがリポジトリにコミットした際に自動である処理を実行したい、といった目的でフック機構が用意されています。

コミットされたら、公開用ディレクトリを更新する

リポジトリの内容をあるディレクトリに展開しておき、リポジトリに新しいコミットが行われたらそのディレクトリを更新する処理をフック機構で自動で実行します。

UNIXでの仕込み

リポジトリ 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で設定がないと、ファイル名をエンコードできずエラーとなります。

Tips

Cygwin関連

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ファイルの情報を修正することでごまかすことが出来そうです。

.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:ignore

未だバージョン管理下に置かれていないファイルおよびディレクトリを、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のあとに""で囲んで複数オプションを指定します。

情報源

書籍・雑誌記事

Web

メーリングリスト

インストールメモ

Windows

どのSubversionを入れようか(2008.11.22記述)

Windows用のSubversionソフトを探すと、現時点では、以下のソフトが見つかります。

コマンドライン版
GUI版(クライアント機能のみ使えればよいなら)

Solaris

Solaris 10 Subversion設定

CentOS

CentOS 5へのインストール

CentOS 5では、Subversion 1.4.2が標準搭載されています。

Subversion 1.5をCentOS 5へインストールするメモはこちらです。

CollabNet Subversion 1.6をCentOS 5へインストールするメモはこちらです。

CentOS 4.4へのインストール

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の基本機能が利用できるようになります。

inet経由でsvnserveを起動

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  ]
#

GUI版

Linuxで使えるGUIのSubversionツール

外部diff/mergeツールには、

外部diff/mergeツールの設定(meld)

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"