ときどき、いくつかの別のチェックアウトによって、一つの作業 コピーを作るのが便利なことがあります。たとえば、リポジトリの別々の場所に ある異なるサブディレクトリがほしいとか、リポジトリ自体が別であるとかです。 そのようなことを手で設定することももちろんできます— 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
オプションを指定すれば解決します。