解决你的外部依赖 -- svn:externals

在日常的项目版本管理中, 根据自己的需要, 我们很有可能需要把不同的repository放到不同的目录中, 又或者把几个repository放到一起. 多数时候, 这都是为了解决build中的依赖, 所以这种"个性化"的结构是应该共享, 成为版本的其中一个部分. 否则项目成员就需要各自建立这样的结构, 风格不一, 也有可能造成遗漏.

Subversion 内嵌的property就支持这样的一种属性:svn:externals.

我们先来看一个例子: 假如我们有个calc的工程. 它依赖于一些第三方的声音文件, 放在了red-bean.com中. 先来看看设置好的属性:
$ svn propget svn:externals calc
third-party/sounds http://sounds.red-bean.com/repos

这样,当我们需要checkout这个calc项目的时候, 会出现这样的效果:
$ 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


可以看到, 第三方的文件也一同被checkout下来.

由于外部的文件是不可控的,如果总是取用外部最新的修改, 有可能和我们现有版本不配套, 现有的build就有可能不成功. 所以subversion也提供了指定特定的revision的功能. 假设外部项目和我们配套的版本是revision 21, 我们可以这么做, 如:
$ svn propget svn:externals calc
third-party/sounds http://sounds.red-bean.com/repos
third-party/skins/toolkit -r21 http://svn.red-bean.com/repos/skin-maker

这样,当我们下次checkout的时候, 就只会取到revision 21的版本, 这样就不会影响到我们现有的build.

上面提到的主要是获取svn:externals的, 如果需要设置这个属性, 我们主要用的是 svn propset 或者 svn propedit. 需要注意的有两点,
由于svn:externals需要指定的外部项多数都是多行的, 所以推荐使用propedit进行编辑.
这个属性只对目录起作用, 不可以应用在独立的文件当中.

当完成了对svn:externals的修改以后, 每次当你使用update的时候, 相应的外部文件也会被检查并且更新(当然, checkout的时候也是如此).

由于属性也被纳入了subversion的版本管理中, 所以你对目录的修改都是可以上传到服务器上, 和其他的项目成员共享, 并基线化.

这个功能看上去很美, 就像是link一样, 但是也有它的一些先天的不足, 就是这个属性是静态的! 如果svn结构出现变化的时候, 属性并不会根据你的修改而改变, 这些这里引用svn book中的一例子.

假设你有一个目录, 叫做 my-project,  而且你已经在其中一个目录(my-project/some-dir) 上面创建了一个外部定义, 它会从 (myproject/
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 改成 renamed-project. 我们update的时候, 什么事情会发生呢?? 我们看一下:

$ svn move -q my-project renamed-project
$ svn commit -m "Rename my-project to renamed-project."
Deleting my-project
Adding my-renamed-project
Committed revision 12.
$ svn update
Fetching external item into 'renamed-project/some-dir/subdir'
svn: Target path does not exist
$
BAM!! 出错了!

而且,当使用了https作为commit的时候, 也有可能出问题. 这里就留点小关子, 不再这篇文章中赘述, 有兴趣的朋友请阅读SVN book的Charter3, 一定让你获益不少.

你可能感兴趣的:(svn)