有时,构建由多个不同检出组成的工作副本很有用。例如,您可能希望不同的文件或子目录来自存储库中的不同位置,或者可能来自完全不同的存储库。如果您希望每个用户都具有相同的布局,则可以定义 svn:externals
属性以在需要的位置拉取指定的资源。
假设您将 /project1
的工作副本检出到 D:\dev\project1
。选择文件夹 D:\dev\project1
,右键单击 并从上下文菜单中选择 → 。属性对话框将弹出。然后转到 Subversion 选项卡。在那里,您可以设置属性。单击 。在属性对话框中,如果 svn:externals
已经存在,则双击它,或者单击 按钮并从菜单中选择 externals
。要添加新的外部,请单击 ,然后在显示的对话框中填写所需信息。
URL 必须正确转义,否则它们将无法工作,例如,您必须将每个空格替换为 %20
。
如果您希望本地路径包含空格或其他特殊字符,则可以将其用双引号括起来,或者可以使用 \
(反斜杠)字符作为 Unix shell 风格的转义字符,在任何特殊字符之前。当然,这也意味着您必须使用 /
(正斜杠)作为路径分隔符。请注意,此行为是 Subversion 1.6 中的新功能,在旧版客户端中将无法使用。
您应该认真考虑在所有外部定义中使用显式修订号,如上所述。这样做意味着您可以决定何时拉取不同的外部信息快照,以及拉取哪个快照。除了不会被您无法控制的第三方存储库更改所惊讶的常识方面之外,使用显式修订号还意味着,当您将工作副本回溯到以前的修订版时,您的外部定义也将恢复到它们在该先前修订版中的样子,这反过来意味着外部工作副本将更新以匹配 它们 在您的存储库处于该先前修订版时的样子。对于软件项目,这可能是成功构建和失败构建复杂代码库的旧快照之间的区别。
用于svn:externals
属性的编辑对话框允许您选择外部项目并自动将其显式设置为HEAD版本。
如果外部项目位于同一个仓库中,您对外部项目所做的任何更改都将在您提交主项目时包含在提交列表中。
如果外部项目位于不同的仓库中,您对外部项目所做的任何更改将在您提交主项目时显示或指示,但您必须单独提交这些外部更改。
如果您在svn:externals
定义中使用绝对URL,并且您必须重新定位您的工作副本(例如,如果您的仓库的URL更改),那么您的外部项目将不会更改,并且可能不再起作用。
为了避免此类问题,Subversion 客户端版本 1.5 及更高版本支持相对外部 URL。支持四种不同的指定相对 URL 的方法。在以下示例中,假设我们有两个仓库:一个位于http://example.com/svn/repos-1
,另一个位于http://example.com/svn/repos-2
。我们已将http://example.com/svn/repos-1/project/trunk
检出到C:\Working
,并且svn:externals
属性已在trunk上设置。
这些 URL 始终以字符串../
开头,例如
../../widgets/foo common/foo-widget
这将把http://example.com/svn/repos-1/widgets/foo
提取到C:\Working\common\foo-widget
中。
请注意,URL 相对于具有svn:externals
属性的目录的 URL,而不是相对于外部项目写入磁盘的目录。
这些 URL 始终以字符串^/
开头,例如
^/widgets/foo common/foo-widget
这将把http://example.com/svn/repos-1/widgets/foo
提取到C:\Working\common\foo-widget
中。
您可以轻松地引用具有相同SVNParentPath
(包含多个仓库的公共目录)的其他仓库。例如
^/../repos-2/hammers/claw common/claw-hammer
这将把http://example.com/svn/repos-2/hammers/claw
提取到C:\Working\common\claw-hammer
中。
以字符串//
开头的 URL 只复制 URL 的方案部分。这在同一主机名必须使用不同的方案(取决于网络位置)进行访问时很有用;例如,内网中的客户端使用http://
,而外部客户端使用svn+ssh://
。例如
//example.com/svn/repos-1/widgets/foo common/foo-widget
这将根据用于检出C:\Working
的方法提取http://example.com/svn/repos-1/widgets/foo
或svn+ssh://example.com/svn/repos-1/widgets/foo
。
以字符串/
开头的 URL 复制 URL 的方案和主机名部分,例如
/svn/repos-1/widgets/foo common/foo-widget
这将把http://example.com/svn/repos-1/widgets/foo
提取到C:\Working\common\foo-widget
中。但是,如果您从svn+ssh://another.mirror.net/svn/repos-1/project1/trunk
处的另一台服务器检出您的工作副本,那么外部引用将提取svn+ssh://another.mirror.net/svn/repos-1/widgets/foo
。
如果需要,您还可以为 URL 指定一个挂钩版本和操作版本。要了解有关挂钩版本和操作版本的更多信息,请阅读 Subversion 手册中的 相关章节 。
如果您将外部的目标文件夹指定为子文件夹(如上面的示例),请确保所有中间文件夹也已版本化。因此,对于上面的示例,文件夹common
应该被版本化!
虽然在大多数情况下,即使中间文件夹没有版本化,外部也能正常工作,但有些操作将无法按预期执行。并且资源管理器中的状态覆盖图标也不会显示正确的状态。
如果您需要更多关于 TortoiseSVN 如何处理属性的信息,请阅读名为“项目设置”的部分。
要了解访问公共子项目的不同方法,请阅读名为“包含公共子项目”的部分。
从 Subversion 1.6 开始,您可以使用与文件夹相同的语法将单个文件外部添加到您的工作副本中。但是,有一些限制。
文件外部的路径必须是您设置svn:externals
属性的文件夹的直接子级。
文件外部的 URL 必须与文件外部将被插入到的 URL 位于同一个存储库中;不支持跨存储库文件外部。
文件外部在许多方面与任何其他版本化的文件一样,但它们不能使用正常的命令移动或删除;必须修改svn:externals
属性。