作者:zhanhailiang 日期:2012-12-07
急于应用而不想过多耗在概念上的同学请直接使用Windows版本的乌龟(TortoiseSVN)实践,操作步骤直接参见TortoiseSVN手册4.18. External Items
有时候创建一个由多个不同检出得到的工作拷贝是非常有用的,举个例子,你或许希望不同 的子目录来自不同的版本库位置,或者是不同的版本库。你可以手工设置这样一个工作拷贝 —使用svn checkout来创建这种你需要的嵌套的工作拷贝结构。但是如果这个结构对所有的用 户是很重要的,每个用户需要执行同样的检出操作。
很幸运,Subversion提供了外部定义的支持,一个外部定义是一个本地路经到URL的影射—也有 可能一个特定的修订版本—一些版本化的资源。在Subversion你可以使用svn:externals属性来 定义外部定义,你可以用svn propset或svn propedit(见第 3.2.2 节 “操作属性”)创建和修 改这个属性。它可以设置到任何版本化的路经,它的值是一个多行的子目录,可选的修订版本 标记和完全有效的Subversion版本库URL的列表(相对于设置属性的版本化目录)。
svn:externals的方便之处是这个属性设置到版本化的路径后,任何人可以从那个目录取出一个 工作拷贝,同样得到外部定义的好处。换句话说,一旦一个人努力来定义这些嵌套的工作拷贝 检出,其他任何人不需要再麻烦了—Subversion会在原先的工作拷贝检出之后,也会检出外部工 作拷贝。
警告 外部定义的相对目标子目录不需要存在于你的或其它用户的系统中—Subversion会在检出工作拷 贝时创建这些文件。实际上,你一定不要使用外部定义来产生已经在版本控制的路径。
You also get in the externals definition design all the regular benefits of Subversion properties. The definitions are versioned. If you need to change an externals definition, you can do so using the regular property modification subcommands. When you commit a change to the svn:externals property, Subversion will synchronize the checked-out items against the changed externals definition when you next run svn update. The same thing will happen when others update their working copies and receive your changes to the externals definition.
提示 因为svn:externals的值是多行的,所以我们强烈建议使用svn propedit,而不是使用svn propset。
Subversion releases prior to 1.5 honor an externals definition format that is a multiline table of subdirectories (relative to the versioned directory on which the property is set), optional revision flags, and fully qualified, absolute Subversion repository URLs. An example of this might looks as follows:
$ svn propget svn:externals calc third-party/sounds http://svn.example.com/repos/sounds third-party/skins -r148 http://svn.example.com/skinproj third-party/skins/toolkit -r21 http://svn.example.com/skin-maker
注意前一个外部定义实例,当有人取出了一个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 …
As of Subversion 1.5, though, a new format of the svn:externals property is supported. Externals definitions are still multiline, but the order and format of the various pieces of information have changed. The new syntax more closely mimics the order of arguments you might pass to svn checkout: the optional revision flags come first, then the external Subversion repository URL, and finally the relative local subdirectory. Notice, though, that this time we didn't say “fully qualified, absolute Subversion repository URLs.” That's because the new format supports relative URLs and URLs that carry peg revisions. The previous example of an externals definition might, in Subversion 1.5, look like the following:
$ svn propget svn:externals calc http://svn.example.com/repos/sounds third-party/sounds -r148 http://svn.example.com/skinproj third-party/skins -r21 http://svn.example.com/skin-maker third-party/skins/toolkit
Or, making use of the peg revision syntax (which we describe in detail in 第 3.9 节 “Peg 和实施修订版本”), it might appear as:
$ svn propget svn:externals calc http://svn.example.com/repos/sounds third-party/sounds http://svn.example.com/skinproj@148 third-party/skins http://svn.example.com/skin-maker@21 third-party/skins/toolkit
提示 你一定要要慎重考虑在所有的外部定义中使用明确的修订版本,这样做意味着你已经决定了何时拖出外 部信息不同的快照,和精确的拖出哪个快照。除了不会受到第三方版本库的意外修改的影响以外,当你 的工作拷贝回溯到以前的版本库时,使用明确的修订版本号会让外部定义回到以前的那个修订版本,也 意味着外部定义的工作拷贝更新会匹配以前修订版本的样子。对于软件项目,这可能是编译复杂代码基 的老快照成功和失败的区别。
For most repositories, these three ways of formatting the externals definitions have the same ultimate effect. They all bring the same benefits. Unfortunately, they all bring the same annoyances, too. Since the definitions shown use absolute URLs, moving or copying a directory to which they are attached will not affect what gets checked out as an external (though the relative local target subdirectory will, of course, move with the renamed directory). This can be confusing—even frustrating—in certain situations. For example, say you have a top-level directory named my-project, and you've created an externals definition on one of its subdirectories (my-project/some-dir) that tracks the latest revision of another of its subdirectories (my-project/external-dir).
$ svn checkout http://svn.example.com/projects . A my-project A my-project/some-dir A my-project/external-dir … Fetching external item into 'my-project/some-dir/subdir' Checked out external at revision 11. Checked out revision 11. $ svn propget svn:externals my-project/some-dir subdir http://svn.example.com/projects/my-project/external-dir $
现在你使用svn move将目录my-project改名,此刻,你的外部定义还是指向myproject目录,即使这个目 录已经不存在了。
$ svn move -q my-project renamed-project $ svn commit -m "Rename my-project to renamed-project." Deleting my-project Adding renamed-project Committed revision 12. $ svn update Fetching external item into 'renamed-project/some-dir/subdir' svn: Target path does not exist $
Also, absolute URLs can cause problems with repositories that are available via multiple URL schemes. For example, if your Subversion server is configured to allow everyone to check out the repository over http: or https://, but only allow commits to come in via https://, you have an interesting problem on your hands. If your externals definitions use the http: form of the repository URLs, you won't be able to commit anything from the working copies created by those externals. On the other hand, if they use the https: form of the URLs, anyone who might be checking out via http: because his client doesn't support https: will be unable to fetch the external items. Be aware, too, that if you need to reparent your working copy (using svn switch with the –relocate option), externals definitions will not also be reparented. Subversion 1.5 takes a huge step in relieving these frustrations. As mentioned earlier, the URLs used in the new externals definition format can be relative, and Subversion provides syntax magic for specifying multiple flavors of URL relativity. <code> ../ Relative to the URL of the directory on which the svn:externals property is set ^/ Relative to the root of the repository in which the svn:externals property is versioned Relative to the scheme of the URL of the directory on which the svn:externals property is set / Relative to the root URL of the server on which the svn:externals property is versioned </code>
So, looking a fourth time at our previous externals definition example, and making use of the new absolute URL syntax in various ways, we might now see:
$ svn propget svn:externals calc ^/sounds third-party/sounds /skinproj@148 third-party/skins //svn.example.com/skin-maker@21 third-party/skins/toolkit
The support that exists for externals definitions in Subversion remains less than ideal, though. An externals definition can point only to directories, not to files. Also, the local subdirectory part of the definition cannot contain .. parent directory indicators (such as ../../skins/myskin).
Perhaps most disappointingly, the working copies created via the externals definition support are still disconnected from the primary working copy (on whose versioned directories the svn:externals property was actually set). And Subversion still truly operates only on nondisjoint working copies. So, for example, if you want to commit changes that you've made in one or more of those external working copies, you must run svn commit explicitly on those working copies—committing on the primary working copy will not recurse into any external ones.
We've already mentioned some of the additional shortcomings of the old svn:externals format and how the new Subversion 1.5 format improves upon it. But be careful when making use of the new format that you don't inadvertently cause problems for other folks accessing your repository who are using older Subversion clients. While Subversion 1.5 clients will continue to recognize and support the original externals definition format, older clients will not be able to correctly parse the new format.
Besides the svn checkout, svn update, svn switch, and svn export commands which actually manage the disjoint (or disconnected) subdirectories into which externals are checked out, the svn status command also recognizes externals definitions. It displays a status code of X for the disjoint external subdirectories, and then recurses into those subdirectories to display the status of the external items themselves. You can pass the –ignore-externals option to any of these subcommands to disable externals definition processing.