外部定義

ときどき、いくつかの別のチェックアウトによって、一つの作業 コピーを作るのが便利なことがあります。たとえば、リポジトリの別々の場所に ある異なるサブディレクトリがほしいとか、リポジトリ自体が別であるとかです。 そのようなことを手で設定することももちろんできます— svn checkout を使ってネストした作業コピー構造のような ものを作るわけです。しかし、このレイアウトがリポジトリを使うすべての人に とって重要であれば、他の全員もあなたがやったのと同じチェックアウト操作を する必要があります。

幸運なことに、Subversionは外部定義をサポート しています。外部定義は、ローカルディレクトリをバージョン管理された リソースのURL—や特定のリビジョン—に結びつけるものです。Subversionでは、 svn:externals属性を使って外部定義をグループにして 宣言します。svn propsetか、svn propedit コマンドでこの属性を作ったり修正したりすることができます(なぜ属性なんてものが?項を参照してください)。 この属性はバージョン管理されたディレクトリに設定され、 その値は(属性が設定されたバージョン管理されたディレクトリ に相対的な)サブディレクトリと、完全に修飾されたSubversionリポジトリURL の絶対パス名を一行とした複数行テーブルです。

$ svn propget svn:externals calc
third-party/sounds             http://sounds.red-bean.com/repos
third-party/skins              http://skins.red-bean.com/repositories/skinproj
third-party/skins/toolkit -r21 http://svn.red-bean.com/repos/skin-maker

svn:externalsが便利なのは、ひとたびバージョン管理 下のディレクトリに設定してしまえば、そのディレクトリのある作業コピーを チェックアウトした人は誰でも外部定義の恩恵にあずかることができる ところです。言い換えると、誰かがそのようなネストした作業コピーの チェックアウトを定義すれば、他の人は誰もそれについて悩まなくて済む ということです—Subversionは、もともとの作業コピーのチェックアウト の上にも外部作業コピーをチェックアウトすることができます。

前の外部定義の例を見てみましょう。誰かがcalc ディレクトリの作業コピーをチェックアウトすると、Subversionは その外部定義にあるアイテムも続けてチェックアウトします。

$ svn checkout http://svn.example.com/repos/calc
A  calc
A  calc/Makefile
A  calc/integer.c
A  calc/button.c
Checked out revision 148.

Fetching external item into calc/third-party/sounds
A  calc/third-party/sounds/ding.ogg
A  calc/third-party/sounds/dong.ogg
A  calc/third-party/sounds/clang.ogg
…
A  calc/third-party/sounds/bang.ogg
A  calc/third-party/sounds/twang.ogg
Checked out revision 14.

Fetching external item into calc/third-party/skins
…

もし、外部定義を変更する必要がある場合、通常の属性変更 サブコマンドを使ってやることができます。 svn:externals属性への変更をコミットするとき、 Subversionは次のsvn updateを実行するときの 変更された外部定義に対してチェックアウトするアイテムを同期します。 同じことが、他の人が作業コピーを更新し、あなたが変更した外部定義 を受け取るときにも起こります。

svn status コマンドも外部定義がチェックアウトされた サブディレクトリごとにXの状態コードを表示する形で 外部定義を認識し、外部アイテムそれ自身の状態を表示するためにそれらの サブディレクトリに再帰的に降りていきます。

ティップ

外部定義のすべてに明示的なリビジョン番号を使うことを強くお勧めします。 これによって異なる外部定義のスナップショットを引っ張ってくる時にどれを 持ってくれば良いか決めることができ、正しいものを持ってこれるように なります。自分ではまったく制御できないサードパーティーのリポジトリに 対する変更点に対する変更に対して冷静に対処できるという当たり前の利点 のほか、明示的なリビジョン番号はまた、以前のあるリビジョンに作業コピーを 戻す場合に、外部定義もその以前のリビジョンでの内容に戻るわけです が、それはまた、あなたのリポジトリがその以前のリビジョンであった 時に彼らが見たいと思う状態に合う形で外部作業 コピーが更新されることを意味しています。ソフトウェアプロジェクトにおいて これが複雑なソースコードの古いスナップショットを再構築する時の成否の 鍵になります。

しかし現在の Subversion での外部定義のサポートは少し誤解されています。 まず、外部定義はディレクトリだけを指すことができ、ファイルを指すことは できません。次に外部定義は相対パス (../../skins/myskinのようなもの)を指すことはでき ません。さらに外部定義のサポートを通じて作られれた作業コピーは最初の作業コピーとは まだ独立したものです(つまり、svn:externals属性が 実際に設定されているかも知れないバージョン化されたディレクトリからは 独立したものです)。そして Subversion は、この分離されていない作業コピー 上に対してだけ正しく働きます。このため例えば、もし一つ以上のの外部作業 コピーに対して行った変更をコミットしたい場合、その作業コピー上で明示的 にsvn commitを実行する必要があります—最初の作 業コピーでのコミットが外部の作業コピーのコミットを連鎖的に発生させる ことはありません。

またその定義自身もURLの絶対パス名を利用するのでそのパスに関係する ディレクトリの移動やコピーは外部のものとしてチェックアウトした ものに影響を与えません(相対的なローカルターゲットディレクトリはもちろん その名称変更されたディレクトリと共に移動しますが)。これはある種の 状況では混乱の元になるかも知れません—あるいはいらいらさせる かもしれません。たとえば、同じ開発ラインの別の部分を指しているような /trunk開発ライン上のディレクトリで外部定義を 使い、それからsvn copyでそのラインのブランチを どこか別の場所 /branches/my-branchに作ったと すると、新しいブランチ上のアイテムに定義された外部定義はまだ /trunk中のバージョン化されたリソースを参照して います。また、もし作業コピーの親を(svn switch --relocate を使って)再設定する必要がある場合、外部定義がそれに付随することは ありません

最後に、svnのサブコマンドが外部定義を認識しない ようにしたいこともあります。そうしないと外部定義処理の結果として作成 された外部作業コピーに対する処理が実行されてしまうような場合です。 これはサブコマンドに --ignore-externals オプションを指定すれば解決します。