有时,构建一个由多个不同检出项组成的工作副本会很有用。例如,您可能希望不同的文件或子目录来自仓库中的不同位置,或者甚至来自完全不同的仓库。如果您希望每个用户都拥有相同的布局,您可以定义 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
这将提取 http://example.com/svn/repos-1/widgets/foo
或 svn+ssh://example.com/svn/repos-1/widgets/foo
,具体取决于用于检出 C:\Working
的方法。
以字符串 /
开头的 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
属性。