### Peg和实施修订版本 文件和目录的拷贝、移动和改名能力可以让我们可以删除一个对象,然后在同样的路径添加一个新的―这是我们在电脑上对文件和目录经常作的操作,我们认为这些操作都是理所当然的。Subversion很乐意你认为这些操作已经赋予给你,Subversion的文件管理操作是这样的解放,提供了几乎和普通文件一样的操作版本化文件的灵活性,但是灵活意味着在整个版本库的生命周期中,一个给定的版本化的资源可能会出现在许多不同的路径,一个给定的路径会展示给我们许多完全不同的版本化资源。 Subversion可以非常聪明的注意到一个对象的版本历史变化包括一个“地址改变”,举个例子,如果你询问一个曾经上周改过名的文件的所有的日志信息,Subversion会很高兴提供所有的日志―重命名发生的修订版本,外加相关版本之前和之后的修订版本日志,所以大多数时间里,你不需要考虑这些事情,但是偶尔,Subversion会需要你的帮助来清除混淆。 这个最简单的例子发生在当一个目录或者文件从版本控制中删除时,然后一个新的同样名字目录或者文件添加到版本控制,清除了你删除的东西,然后你添加的不是同样的东西,它们仅仅是有同样的路径,我们会把它叫做`/trunk/object`。什么,这意味着询问Subversion来查看`/trunk/object`的历史?你是询问当前这个位置的东西还是你在这个位置删除的那个对象?你是希望询问对这个对象的所有操作还是这个路径的所有对象?很明显,Subversion需要线索知道你真实的想法。 由于移动,版本化资源历史会变得非常扭曲。举个例子,你会有一个目录叫做`concept`,保存了一些你用来试验的初生的软件项目,最终,这个项目变得足够成熟,说明这个注意确实需要一些翅膀了,所以你决定给这个项目一个名字。 [[32](#)] 假定你叫你的软件为Frabnaggilywort,此刻,有必要把你的目录命名为反映项目名称的名字,所以`concept`改名为`frabnaggilywort`。生活还在继续,Frabnaggilywort发布了1.0版本,并且被许多希望改进他们生活的分散用户天天使用。 这是一个美好的故事,但是没有在这里结束,作为主办人,你一定想到了另一件事,所以你创建了一个目录叫做`concept`,周期重新开始。实际上,这个循环在几年里开始了多次,每一个想法从使用旧的`concept`目录开始,然后有时在想法成熟之后重新命名,有时你放弃了这个注意而删除了这个目录。或者更加变态一点,或许你把`concept`改成其他名字之后又因为一些原因重新改回`concept`。 当这样的情景发生时,指导Subversion工作在重新使用的路径上的尝试就像指导一个芝加哥西郊的乘客驾车到东面的罗斯福路并且左转到主大道。仅仅20分钟,你可以穿过惠顿、格伦埃林何朗伯德的“主大道”,但是它们不是一样的街道,我们的乘客―和我们的Subversion―需要更多的细节来做正确的事情。 在1.1版本,Subversion提供了一种方法来说明你所指是哪一个街道,叫做*peg修订版本*,这是一个提供给Subversion的一个区别一个独立历史线路的单独目的修订版本,因为一个版本化的文件会在任何时间占用某个路径―路径和peg修订版本的合并是可以指定一个历史的特定线路。Peg修订版本可以在Subversion命令行客户端中用*at语法*指定,之所以使用这个名称是因为会在关联的修订版本的路径后面追加一个“at符号”(`@`)。 但是我们在本书多次提到的`--revision (-r)`到底是什么?修订版本(或者是修订版本集)叫做*实施的修订版本*(或者叫做*实施的修订版本范围*),一旦一个特定历史线路通过一个路径和peg修订版本指定,Subversion会使用实施的修订版本执行要求的操作。类似的,为了指出这个到我们芝加哥的道路,如果我们被告知到惠顿主大道606号, [[33](#)] 我们可以把“主大道”看作路径,把“惠顿”当作我们的peg修订版本。这两段信息确认了我们可以旅行(主大道的北方或南方)的唯一路径,也会保持我们不会在前前后后寻找目标时走到错误的主大道。现在我们把“606 N.”作为我们实施的修订版本,我们*精确的*知道到哪里。 当使用peg和实施修订版本来查找我们需要工作文件时,Subversion会执行一个很直接的算法。首先,找到与peg修订版本相关的路径坐落于版本库的那个修订版本,Subversion开始从那里开始向后查询这个对象的历史前辈。每个前辈表示这个对象的以前的一个版本,每一个版本的对象都保存了自己被创建的修订版本和路径,所以通过前辈集,Subversion可以注意到哪个版本是这个实施修订版本最年轻的版本,如果是,可以将实施修订版本影射到前辈创建的路径/创建修订版本对。算法在所有的实施修订版本影射到真实的对象位置后,或者是没有更多的前辈时完成,就是任何未影射的实施修订版本已经标记为不符合操作的对象。 也就是说很久以前我们创建了我们的版本库,在修订版本1添加我们第一个`concept`目录,并且在这个目录增加一个`IDEA`文件与concept相关,在几个修订版本之后,真实的代码被添加和修改,我们在修订版本20,修改这个目录为`frabnaggilywort`。通过修订版本27,我们有了一个新的概念,所以一个新的`concept`目录用来保存这些东西,一个新的`IDEA`文件来描述这个概念,然后经过5年20000个修订版本,就像他们都有一个非常浪漫的历史。 现在,一年之后,我们想知道`IDEA`在修订版本1时是什么样子,但是Subversion需要知道我们是想询问*当前*文件在修订版本1时的样子,还是希望知道`concepts/IDEA`在修订版本1时的那个文件?确定这些问题有不同的答案,并且因为peg修订版本,你可以用两种方式询问。为了知道当前的`IDEA`文件在旧版本1的样子,我们可以运行: ~~~ $ svn cat -r 1 concept/IDEA subversion/libsvn_client/ra.c:775: (apr_err=20014) svn: Unable to find repository location for 'concept/IDEA' in revision 1 ~~~ 当然,在这个例子里,当前的`IDEA`文件在修订版本1中并不存在,所以Subversion给出一个错误,这个上面的命令是长的peg修订版本命令一个缩写,扩展的写法是: ~~~ $ svn cat -r 1 concept/IDEA@BASE subversion/libsvn_client/ra.c:775: (apr_err=20014) svn: Unable to find repository location for 'concept/IDEA' in revision 1 ~~~ 当执行时会有预料中的结果,当应用到工作拷贝路径时,Peg修订版本通常缺省值是`BASE`(在当前工作拷贝现在的修订版本),当应用到URL时,缺省值是`HEAD`。 然后让我们询问另一个问题―在修订版本1 ,占据`concepts/IDEA`路径的文件的内容到底是什么?我们会使用一个明确的peg修订版本来帮助我们完成。 ~~~ $ svn cat concept/IDEA@1 The idea behind this project is to come up with a piece of software that can frab a naggily wort. Frabbing naggily worts is tricky business, and doing it incorrectly can have serious ramifications, so we need to employ over-the-top input validation and data verification mechanisms. ~~~ 这看起来是正确的输出,这些文本甚至提到“frabbing naggily worts”,所以这就是现在叫做Frabnaggilywort项目的那个文件,实际上,我们可以使用显示的peg修订版本和实施修订版本的组合核实这一点。我们知道在`HEAD`,Frabnaggilywort项目坐落在`frabnaggilywort`目录,所以我们指定我们希望看到`HEAD`的`frabnaggilywort/IDEA`路经在历史上的修订版本1的内容。 ~~~ $ svn cat -r 1 frabnaggilywort/IDEA@HEAD The idea behind this project is to come up with a piece of software that can frab a naggily wort. Frabbing naggily worts is tricky business, and doing it incorrectly can have serious ramifications, so we need to employ over-the-top input validation and data verification mechanisms. ~~~ 而且peg修订版本和实施修订版本也不需要这样琐碎,举个例子,我们的`frabnaggilywort`已经在`HEAD`删除,但我们知道在修订版本20它是存在的,我们希望知道`IDEA`从修订版本4到10的区别,我们可以使用peg修订版本20和`IDEA`文件的修订版本20的URL的组合,然后使用4到10作为我们的实施修订版本范围。 ~~~ $ svn diff -r 4:10 http://svn.red-bean.com/projects/frabnaggilywort/IDEA@20 Index: frabnaggilywort/IDEA =================================================================== --- frabnaggilywort/IDEA (revision 4) +++ frabnaggilywort/IDEA (revision 10) @@ -1,5 +1,5 @@ -The idea behind this project is to come up with a piece of software -that can frab a naggily wort. Frabbing naggily worts is tricky -business, and doing it incorrectly can have serious ramifications, so -we need to employ over-the-top input validation and data verification -mechanisms. +The idea behind this project is to come up with a piece of +client-server software that can remotely frab a naggily wort. +Frabbing naggily worts is tricky business, and doing it incorrectly +can have serious ramifications, so we need to employ over-the-top +input validation and data verification mechanisms. ~~~ 幸运的是,几乎所有的人们不会面临如此复杂的情形,但是如果是,记住peg修订版本是帮助Subversion清除混淆的额外提示。 “你不是被期望去命名它,一旦你取了名字,你开始与之联系在一起。” ― Mike Wazowski 伊利诺伊州惠顿主大道606号市惠顿离市中心,让它作为―“历史中心”?看起来是恰当的…。