外部定义

有时候创建一个由多个不同检出得到的工作拷贝是非常有用的,举个例子,你或许希望不同的子目录来自不同的版本库位置,或者是不同的版本库。你可以手工设置这样一个工作拷贝—使用svn checkout来创建这种你需要的嵌套的工作拷贝结构。但是如果这个结构对所有的用户是很重要的,每个用户需要执行同样的检出操作。

很幸运,Subversion提供了外部定义的支持,一个外部定义是一个本地路经到URL的影射—也有可能一个特定的修订版本—一些版本化的资源。在Subversion你可以使用svn:externals属性来定义外部定义,你可以用svn propsetsvn 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属性修改后,当你运行svn update时,Subversion会根据修改的外部定义同步检出的项目,同样的事情也会发生在别人更新他们的工作拷贝接受你的外部定义修改时。

svn status命令也认识外部定义,会为外部定义的子目录显示X状态码,然后迭代这些子目录来显示外部项目的子目录状态信息。

Subversion目前对外部定义的支持可能会引起误导,首先,一个外部定义只可以指向目录,而不是文件。第二,外部定义不可以指向相对路径(如../../skins/myskin)。第三,同过外部定义创建的工作拷贝与主工作拷贝没有连接,所以举个例子,如果你希望提交一个或多个外部定义的拷贝,你必须在这些工作拷贝显示的运行svn commit—对主工作拷贝的提交不会迭代到外部定义的部分。

另外,因为定义本身使用绝对路径,移动和拷贝路径他们附着的路径不会影响他们作为外部的检出(尽管相对的本地目标子目录会这样,当然,根据重命名的目录)。这看起来有些迷惑—甚至让人沮丧—在特定情形。举个例子,如果你在/trunk开发线对一个目录使用外部定义,指向同一条线上的其他区域,然后使用svn copy把分支开发线拷贝到/branches/my-branch这个新位置,这个项目新分支的外部定义仍然指向/trunk版本化资源。另外,需要意识到如果你需要一个重新规划你的工作拷贝的父目录(使用svn switch --relocate),外部定义会重新选择父目录。