作業コピーについてはすでに説明したとおりですので、今度は Subversion クライアントでどのように作業コピーを作成したり使用したりするかを見ていきましょう。
Subversion の作業コピーは、ローカルシステム上にある通常のディレクトリツリーで、ここにファイルが集められています。お望みのファイルをどれでも編集することができますし、それがソースコードのファイルなら、いつも通りそのファイルからプログラムをコンパイルできます。作業コピーは自分の個人的な作業場所です。 Subversion が他人の変更をここに組み込むことはありませんし、同様に、明確に指示するまで自分の変更が他人に公開されることもありません。
作業コピーのファイルに変更を加え、それがうまく動作することを確認したあとで、その変更を同じプロジェクトで一緒に作業しているほかの人に(リポジトリに書き込むことで) 公開 するためのコマンドが Subversion には用意されています。また、他の人の変更が公開されたときは、その変更を(リポジトリから読み出して)自分の作業コピーにマージするコマンドが用意されています。
作業コピーには、 Subversion のコマンドの実行を補助するために、作成・保守される特別なファイルがあります。具体的には、作業コピーの中に .svn
という名前のサブディレクトリが作られます。これは作業コピーの 管理ディレクトリ として知られています。管理ディレクトリ内のファイルは、まだ公開していない変更があるか、また他の人の作業によって最新でなくなっているかを Subversion が認識する助けになります。 Subversion 1.7 以前では、 .svn
ディレクトリは作業コピー内のバージョン管理対象のディレクトリそれぞれに作られていました。 Subversion 1.7 で完全に方法が変更され、各作業コピーが持つ管理ディレクトリは作業コピーのルートの直下に1つだけ作られるようになりました。
典型的な Subversion リポジトリでは、いくつものプロジェクトのファイル(やソースコード)を保持し、リポジトリのファイルシステムツリー以下に、プロジェクトごとのサブディレクトリを置いています。この配置では、ユーザーの作業コピーは大抵リポジトリの特定のサブツリーに相当します。
例えば、2つのソフトウェアプロジェクトがあるリポジトリがあったとします。
具体的には、リポジトリのルートディレクトリに paint
と calc
というサブディレクトリがあります。
作業コピーを取得するために、リポジトリのサブツリーを チェックアウト しなければなりません(チェックアウト は、リソースのロックや予約が必要なように思われますが、そんなことはありません。単に、プロジェクトのプライベートなコピーを作成するだけです)。
button.c
を変更したとしましょう。 .svn
ディレクトリには、ファイルの変更日時と元の内容が記録されていますから、 Subversion はファイルが変更されていることがわかります。しかし、変更は明確に指示するまで公開はされません。変更を公開する操作は通常、変更をリポジトリへ コミット する(もしくは チェックイン する)と呼ばれています。
変更を他の人に公開するには、 Subversion のコミット(commit)コマンドを使用します。
さて、 button.c
への変更を、リポジトリにコミットした後で、他のユーザーが /calc
の作業コピーをチェックアウトすると、変更が反映された最新版のファイルが取得されます。
自分にサリーという相棒がいて、 /calc
の作業コピーを自分と同時にチェックアウトしたとします。自分が button.c
の変更をコミットしても、サリーの作業コピーは変更されません。 Subversion はユーザーが操作しないと作業コピーを更新しないからです。
サリーのプロジェクトを最新状態にするには、Subversion に作業コピーを 更新 するよう指示します。これは Subversion の更新(update)コマンドを使用します。これによって、自分の変更がサリーの作業コピーに組み込まれ、またチェックアウト後にコミットされた他の人の変更も同様に組み込まれます。
サリーは、どのファイルを更新するかを指定する必要はありません。Subversion は .svn
ディレクトリの情報とリポジトリ内の詳細情報を使用して、どのファイルを更新するか決めるのです。
Subversion のリポジトリは、ローカルディスクや様々なネットワークプロトコル経由など、多様な方法でアクセスできます。しかし、リポジトリの位置は常に URL で表します。 URL スキーマはアクセス方法を表します。
表2.1 リポジトリにアクセスするURL
スキーマ | アクセス方法 |
---|---|
file://
| ローカルないしネットワークドライブのリポジトリに直接アクセスします。 |
http://
| Subversion を組み込んだ Apache サーバーに WebDAV プロトコルでアクセスします。 |
https://
| http:// と同じですが、SSL 暗号化を用います。 |
svn://
| 認証のない TCP/IP による独自プロトコルで svnserve サーバーにアクセスします。 |
svn+ssh://
| 認証・暗号化された TCP/IP による独自プロトコルで svnserve サーバーにアクセスします。 |
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 ...
Windows の(URL以外の)パスの形式ではバックスラッシュを使用しますが、URLには通常スラッシュを使用することに注意してください。
ネットワークフォルダー上でもFSFSリポジトリにはアクセスできますが、これはさまざまな理由によりお勧めできません。
すべてのユーザーに直接書き込む権限を与えてしまうので、誰かが誤ってリポジトリファイルシステムを削除したり破壊したりしてしまうことがあります。
すべてのネットワークファイル共有プロトコルが、 Subversion が要求するロック機能をサポートしているわけではありません。いつか、リポジトリが潜在的に壊れてしまうかもしれません。
アクセス権を正しく設定する必要があります。Sambaはこの要求には難しい部分があります。
誰かが新しいバージョンのクライアントをインストールしてリポジトリのフォーマットをアップグレードすると、全員が新しいバージョンのクライアントにアップグレードするまで、リポジトリにアクセスできなくなります。
svn commit (コミット)の操作は、ファイルやディレクトリの変更を、単一の不可分トランザクションで公開します。作業コピーで、ファイル内容の変更、ファイルやディレクトリの作成、削除、名前の変更、コピーなど行い、それ全体を単位とした完全な変更セットをコミットできます。
リポジトリでは、コミットを不可分トランザクションとして扱い、変更をすべて配置するか、何も配置しないかのどちらかになります。 Subversion はプログラムの異常終了や、システムの異常終了、ネットワーク障害、他のユーザーの操作に直面しても、この最小単位を保持しようとします。
リポジトリがコミットを受け付けるごとに、ファイルシステムツリーの状態が新しく作成されます。これを リビジョン と呼びます。リビジョンごとに一意の自然数が割り当てられ、直前のリビジョンよりも1だけ大きくなります。リポジトリを新規作成した直後のリビジョンは 0 で、ルートディレクトリ以外はなにも含まれていません。
リポジトリを視覚化するよい方法は、ツリーの連続で表すというものです。 0 から始まるリビジョン番号の配列が、左から右に追加されていく状況を想像してください。それぞれのリビジョン番号には対応したファイルシステムツリーがあり、それぞれのツリーはコミット後のリポジトリの状態を示す「スナップショット」です。
作業コピーが、リポジトリの特定のリビジョンに常に対応しているとは限らないということに充分注意してください。複数の異なるリビジョンが混在している可能性があります。たとえば、最新のリビジョンが 4 であるリポジトリから、作業コピーをチェックアウトしたとします。
calc/Makefile:4 integer.c:4 button.c:4
この時点では作業ディレクトリは、リポジトリのリビジョン 4 と完全に一致します。しかし、ここで button.c
に変更を加え、変更をコミットしたとします。他にコミットした人がいなければ、このコミットではリポジトリにリビジョン 5 を作成し、作業コピーの内容は以下のようになります。
calc/Makefile:4 integer.c:4 button.c:5
この時点で、サリーが integer.c
を変更し、リビジョン 6 を作成したとします。 svn update で自分の作業コピーを更新すると、以下のようになります。
calc/Makefile:6 integer.c:6 button.c:6
サリーの integer.c
への変更は、自分の作業コピーに現れますが、 button.c
へ行った自分の変更はそのままです。この例では、Makefile
の内容はリビジョン 4、5、6 で全く同じものですが、 Subversion は作業コピー中の Makefile
のリビジョンを 6 にして、最新であることを表現します。そのため作業コピーのトップでまっさらな更新を行うと、一般的に、作業コピーはリポジトリの特定のリビジョンに完全に一致します。
作業ディレクトリ内のファイルに対して、Subversion は2つの本質的な情報を .svn/
管理領域に記録します。
作業しているファイルが基づいているリビジョン(これは 作業リビジョン と呼ばれる)、および、
ローカルコピーをリポジトリから更新したときに記録したタイムスタンプ、です。
この情報とリポジトリとのやりとりによって、 Subversion は、作業ファイルが以下の4つの状態のどれかを確認できます。
作業ディレクトリのファイルが変更されておらず、作業リビジョン以降に行われたリポジトリへのコミットでもそのファイルが変更されていない状態です。そのファイルに対するコミット(commit)は何も行われないし、更新(update)も何も行われません。
作業ディレクトリのファイルは変更されているが、作業リビジョン以降に行われたリポジトリへのコミットではそのファイルが変更されていない状態です。ローカルにはコミットしていない変更があるので、そのファイルに対するコミット(commit)は成功し、ローカルの変更が公開されます。また、更新(update)では何も行われません。
作業ディレクトリのファイルは変更されていないが、リポジトリ上のファイルは変更されている状態です。このファイルを最新の公開リビジョンにするため、どこかで更新しなければなりません。このファイルへのコミット(commit)は何も行われませんが、更新(update)では作業コピーに最新の変更が反映されます。
ファイルは作業ディレクトリでも、リポジトリ上でも変更された状態です。このファイルへのコミット(commit)は 作業コピーは最新ではありません というエラーになります。まず、そのファイルを更新しなければなりません。ファイルに対して更新(update)を行うと、公開されている変更点が、ローカルで変更を行った作業コピーにマージされます。これが自動的にできないような状況の場合、ユーザーが競合の解決を行うため、そのままになります。