Subversion の動作

作業コピー

作業コピーについてはすでに説明したとおりですので、今度は Subversion クライアントで作業コピーの作成・使用について見ていきましょう。

Subversion の作業コピーは、手元のシステム上にある通常のディレクトリツリーで、ここにファイルが集められています。お望みのファイルをどれでも編集することができますし、それがソースコードのファイルなら、いつも通りそのファイルからプログラムをコンパイルできます。作業コピーはあなたの個人的な作業エリアです。Subversion が他の人の変更をここに組み込むことはありませんし、同様に、明示されるまであなたの変更が他の人から使用できるようになることもありません。

作業コピーのファイルに変更を加え、それがうまく動作することを確認したあとで、Subversion はその変更を同じプロジェクトであなたと一緒に 作業しているほかの人に 公開 するためのコマンドを (リポジトリに書き込むことで) 用意します。もし他の人が自分自身の変更を公開したとき にはSubversionはその変更を自分の作業コピーにマージするコマンドを (リポジトリの内容を読み出して) 用意します。

作業コピーには、Subversion によって作成・保守される特別なファイルがあり、その助けを受けてコマンドを実行します。特に作業コピーのディレクトリごとに .svn という名前のサブディレクトリがあり、これは作業コピーの 管理ディレクトリ として知られています。管理ディレクトリのそれぞれのファイルは、まだ公開していない変更があるか、また他の人の作業によって最新でなくなっているかを Subversion が認識する助けになります。

典型的な Subversion リポジトリは、いくつものプロジェクトのファイル (やソースコード) を保持し、リポジトリのファイルシステムツリー以下に、プロジェクトごとのサブディレクトリがあります。この配置では、ユーザの作業コピーは大抵リポジトリの特殊なサブツリーに相当します。

例えば、2 つのソフトウェアプロジェクトがあるリポジトリがあったとします。

図2.6 リポジトリのファイルシステム

リポジトリのファイルシステム

言い換えると、リポジトリのルートディレクトリに paintcalc というサブディレクトリがあります。

作業コピーを取得するのに、チェックアウト をリポジトリのサブツリーに対して行わなければなりません。チェックアウト という用語はロックやリソース確保のように聞こえますがそうではなく、単にあなた専用のコピーを作成することです。

button.c への変更を行うことを思い浮かべてください。.svn ディレクトリはファイルの変更日付と元の内容を記憶していますから、Subversion はファイルが変更されていることを教えてくれます。しかし、あなたの行った変更を (あなたが明示するまで) 公開にしません。あなたが変更を公開することは、リポジトリへのコミット (やチェックイン) と呼ばれています。

あなたの変更を他の人に公開するには、Subversion の commit コマンドを使用してください。

さて、button.c への変更を、リポジトリにコミットしましたから、他のユーザが /calc の作業コピーをチェックアウトすると、あなたが行った変更が入っている最新版のファイルを見ることになります。

あなたに Sally という相棒がいて、/calc の作業コピーをあなたと同時にチェックアウトしたとします。あなたが button.c の変更をコミットしても、Sally の作業コピーは変更されないままです。Subversion はユーザのリクエストによってのみ作業コピーを更新するからです。

Sally のプロジェクトを最新にするには、Subversion に作業コピーを更新するよう指示します。これは Subversion の update コマンドを使用します。これによりあなたの変更が Sally の作業コピーに組み込まれ、またチェックアウト後にコミットされた他の人の変更も同様に組み込まれます。

Sally がどのファイルを更新するか指定する必要がないことに注意してください。Subversion は .svn ディレクトリの情報とリポジトリ内の詳細情報を用い、どのファイルを更新するか決めるのです。

リポジトリ URL

Subversion リポジトリはたくさんの異なる方法 (ローカルディスクや様々なネットワークプロトコル) でアクセスできます。しかし、リポジトリの位置は常に URL で表されます。URL スキーマはアクセス方法を表します。

表2.1 リポジトリアクセス URL

スキーマアクセス方法
file:// ローカルないしネットワークドライブのリポジトリに直接アクセスします。
http:// Subversion を組み込んだ Apache サーバに WebDAV プロトコルでアクセスします。
https:// http:// と同じですが、SSL 暗号化を用います。
svn:// svnserve サーバと独自プロトコルで行う、認証されていない TCP/IP アクセス。
svn+ssh:// svnserve サーバと独自プロトコルで行う、認証・暗号化された TCP/IP アクセス。

ほとんどの場合、Subversion の URL には標準文法を使用し、URL の中にサーバ名やポート番号を含められます。file:// アクセスメソッドは通常ローカルアクセスに使用しますが、ネットワーク上のホストに対する UNC パスにも使用できます。そのため URL は file://hostname/path/to/repos といった形式になります。ローカルマシンでは URL の hostname の部分を空にするか localhost としてください。このためローカルパスは、file:///path/to/repos のようにスラッシュが 3 つ並ぶことになります。

また Windows プラットフォームで file:// スキームを使うユーザは、同じマシン上にあるが、クライアントのカレントドライブとは別のドライブにあるリポジトリにアクセスするために、非公式の標準構文を使う必要があります。以下の URL パス構文のどちらか一方を使えばうまくアクセスできます。ここで X はリポジトリのあるドライブです。

file:///X:/path/to/repos
...
file:///X|/path/to/repos
...

URL は通常スラッシュを使用しますが、Windows のパス形式 (URL ではない) はバックスラッシュを用います。

ネットワーク共有上でも FSFS リポジトリには安全にアクセスできますが、BDB リポジトリにはこの方法でアクセスできません

警告

ネットワーク共有上で Berkeley DB リポジトリを、作成したりアクセスしたりしないでください。これはリモートファイルシステム上に存在できません。ドライブレターにマッピングしたネットワークドライブでもダメです。ネットワーク共有上で Berkeley DB を使おうとした場合、(すぐに不可思議なエラーに遭遇するか、数ヶ月後にリポジトリデータベースが破損するか) 結果が予想できません。

リビジョン

svn commit 操作はファイルやディレクトリの変更を、単一の不可分トランザクションで公開します。作業コピーでは、ファイルの内容を変更したり、ファイルやディレクトリの作成・削除・名前変更・コピーを、完全な変更セットの単位としてコミットできます。

リポジトリでは、コミットを不可分トランザクションとして扱い、全てをそこに置くか何も置かないかのどちらかになります。Subversion はプログラムのクラッシュや、システムクラッシュ、ネットワーク障害、他のユーザの操作に直面してもこの最小単位を保持しようとします。

リポジトリがコミットを受け付けるごとに、ファイルシステムツリーの状態が新しく作成されます。これを リビジョン と呼びます。リビジョンごとに一意の自然数が割り当てられ、前のリビジョンよりも大きくなります。リポジトリを新規作成した直後のリビジョンは 0 で、ルートディレクトリ以外はなにも含まれていません。

リポジトリを視覚化するうまい方法は、ツリーの連続で表すというものです。0 から始まるリビジョン番号が、左から右に追加されていく状況を想像してください。それぞれのリビジョン番号には対応したファイルシステムツリーがあり、それぞれのツリーはコミット後のリポジトリの状態を示すスナップショットです。

図2.7 リポジトリ

リポジトリ

作業コピーがリポジトリの特定のリビジョンに常に対応しているとは限らないということに十分注意してください。複数の異なるリビジョンが混在する可能性があります。たとえば、最新リビジョンが 4 であるリポジトリから、作業コピーをチェックアウトしたとします。

calc/Makefile:4
     integer.c:4
     button.c:4

この時点では作業ディレクトリは、リポジトリのリビジョン 4 と完全に一致します。しかし、ここで button.c に変更を加え、変更をコミットしたとします。他にコミットした人がいなければ、このコミットではリポジトリにリビジョン 5 を作成し、作業コピーの内容は以下のようになります。

calc/Makefile:4
     integer.c:4
     button.c:5

この時点で、Sally がinteger.c を変更し、リビジョン 6 を作成したとします。svn update であなたの作業コピーを更新すると、以下のようになります。

calc/Makefile:6
     integer.c:6
     button.c:6

Sally の integer.c への変更は、あなたの作業コピーに現れますが、button.c へ行ったあなたの変更はそのままです。この例では、Makefile のテキストはリビジョン 4, 5, 6 で全く同じものですが、Subversion は作業コピー中の Makefile のリビジョンを 6 にして最新であることを表現します。そのため作業コピーのトップでまっさらな更新を行うと、一般的に、作業コピーはリポジトリの特定のバージョンに完全に一致します。

作業コピーのリポジトリ追跡方法

作業ディレクトリ内のファイルに対して、Subversion は 2 つの本質的な情報を .svn/ 管理領域に記録します。

  • 作業しているファイルはどのリビジョンを基にしている (これは 作業リビジョン と呼ばれる) か。また、

  • 手元のコピーをリポジトリから更新したときに記録したタイムスタンプ。

この情報とリポジトリとのやりとりによって、Subversion は、作業ファイルが以下の4つの状態のどれかを確認できます。

変更なし、かつ最新

作業ディレクトリのファイルは更新されておらず、作業リビジョン以降に起きたリポジトリへのコミットでもそのファイルに変更がない状態。そのファイルへの コミット は何も行わないし、更新 も何も行いません。

手元で更新、かつ最新

作業ディレクトリが更新されており、その基になったリビジョン以降のリポジトリへのコミットではそのファイルに変更がない状態。手元にはコミットしていない変更があるので、そのファイルへの コミット は成功します。また、更新 ではそのファイルへは何も行いません。

変更なし、かつ最新ではない

作業ディレクトリのファイルに変更はないが、リポジトリには変更がある状態。このファイルを現在の公開リビジョンにするためどこかで更新しなければなりません。このファイルへの コミット はなにもしませんが、更新 は作業コピーへ最新の変更を格納します。

手元で更新、かつ最新ではない

ファイルは作業コピーでも、リポジトリでも変更されています。 ファイルに対する commitout-of-date エラーになります。まず、そのファイルを更新しなくてはなりません。ファイルに対する update は公開されている変更点 を作業コピーの変更にマージしようとします。これが自動的にできないような状況の場合、ユーザが競合の解消を行うため、Subversion はそのままにしておきます。