如果你是从头到尾按章节阅读本书,你一定已经具备了使用Subversion客户端执行大多数不同的版本控制操作足够的知识,你理解了怎样从Subversion版本库取出一个工作拷贝,你已经熟悉了通过svn commit和svn update来提交和接收修改,你甚至也经常下意识的使用svn status,无论目的是什么,你已经可以正常使用Subversion了。
但是Subversion的特性并没有止于“普通的版本控制操作”,它也有一些超越了与版本库传递文件和目录修改以外的功能。
本章重点介绍了一些很重要但不是经常使用的Subversion特性,本章假定你熟悉Subversion对文件和目录的基本版本操作能力,如果你还没有阅读这些内容,或者是需要一个复习,我们建议你重读第 1 章 基本概念和第 2 章 基本使用,一旦你已经掌握了基础知识和本章的内容,你会变成Subversion的超级用户!
Revision Specifiers
As we described in the section called “Revisions”, revision numbers in Subversion are pretty straightforward—integers that keep getting larger as you commit more changes to your versioned data. Still, it doesn't take long before you can no longer remember exactly what happened in each and every revision. Fortunately, the typical Subversion workflow doesn't often demand that you supply arbitrary revisions to the Subversion operations you perform. For operations that do require a revision specifier, you generally supply a revision number that you saw in a commit email, in the output of some other Subversion operation, or in some other context that would give meaning to that particular number.
But occasionally, you need to pinpoint a moment in time for which you don't already have a revision number memorized or handy. So besides the integer revision numbers, svn allows as input some additional forms of revision specifiers: revision keywords and revision dates.
The various forms of Subversion revision specifiers can be mixed and matched when used to specify revision ranges. For example, you can use -r
where REV1
:REV2
REV1
is a revision keyword and REV2
is a revision number, or where REV1
is a date andREV2
is a revision keyword, and so on. The individual revision specifiers are independently evaluated, so you can put whatever you want on the opposite sides of that colon.
版本清单
就像你在“修订版本”一节见到的,Subversion的修订版本号码非常直接—就是随提交增大的整数。尽管如此,不会花很长时间你就会忘记每个修订版本的修改,但幸运的是,典型的Subvesion工作流程中一般不会要求你提供任意的修订版本号。在需要输入修订版本号时,通常或者是你在一个提交邮件中看到了一个修订版本,或者是在其他Subversion命令的输出结果中,或者是任何上下文环境得到某个版本号码的情况下。
但是有时候,你需要精确指定一个时间,而无法记住或者记录了某个版本,这时除了使用修订版本号码,svn允许使用其他形式来指定修订版本—修订版本关键字和修订版本日期。
当用来指定修订版本范围时,不同形式的Subversion修订版本可以混合匹配。例如,你可以REV1
是修订版本关键字,REV2
是修订版本号,或者是REV1
是日期,而REV2
是修订版本关键字,等等。不同的修订版本指定符是等价的,所以你可以在冒号两边任意使用。
The Subversion client understands a number of revision keywords. These keywords can be used instead of integer arguments to the --revision
(-r
) option, and are resolved into specific revision numbers by Subversion:
HEAD
-
The latest (or “youngest”) revision in the repository.
BASE
-
The revision number of an item in a working copy. If the item has been locally modified, this refers to the way the item appears without those local modifications.
工作拷贝中一个条目的修订版本号,如果这个版本在本地修改了,则“BASE版本”就是这个条目在本地未修改的版本。
COMMITTED
-
The most recent revision prior to, or equal to,
BASE
, in which an item changed.项目最近修改的修订版本,与
BASE
相同或更早。 PREV
-
The revision immediately before the last revision in which an item changed. Technically, this boils down to
COMMITTED
−1.一个项目最后修改版本之前的那个版本,技术上可以认为是
COMMITTED
-1。
As can be derived from their descriptions, the PREV
, BASE
, and COMMITTED
revision keywords are used only when referring to a working copy path—they don't apply to repository URLs. HEAD
, on the other hand, can be used in conjunction with both of these path types.
因为可以从描述中得到,关键字PREV
,BASE
和COMMITTED
只在引用工作拷贝路径时使用,而不能用于版本库URL,而关键字HEAD
则可以用于两种路径类型。注意:HEAD针对于版本库,另外3个针对于某个工作副本目录或文件。
下面是一些修订版本关键字的例子:
Here are some examples of revision keywords in action:
$ svn diff -r PREV:COMMITTED foo.c # shows the last change committed to foo.c $ svn log -r HEAD # shows log message for the latest repository commit $ svn diff -r HEAD # compares your working copy (with all of its local changes) to the # latest version of that tree in the repository $ svn diff -r BASE:HEAD foo.c # compares the unmodified version of foo.c with the latest version of # foo.c in the repository $ svn log -r BASE:HEAD # shows all commit logs for the current versioned directory since you # last updated $ svn update -r PREV foo.c # rewinds the last change on foo.c, decreasing foo.c's working revision $ svn diff -r BASE:14 foo.c # compares the unmodified version of foo.c with the way foo.c looked # in revision 14
版本日期Revision Dates
在版本控制系统以外,修订版本号码是没有意义的,但是有时候你需要将时间和历史修订版本号关联。为此,--revision (-r)
选项接受使用花括号({
和}
)包裹的日期输入,Subversion支持标准ISO-8601日期和时间格式,也支持一些其他的。下面是一些例子。(记住使用引号括起所有包含空格的日期。
$ svn checkout -r {2006-02-17} $ svn checkout -r {15:30} $ svn checkout -r {15:30:00.200000} $ svn checkout -r {"2006-02-17 15:30"} $ svn checkout -r {"2006-02-17 15:30 +0230"} $ svn checkout -r {2006-02-17T15:30} $ svn checkout -r {2006-02-17T15:30Z} $ svn checkout -r {2006-02-17T15:30-04:00} $ svn checkout -r {20060217T1530} $ svn checkout -r {20060217T1530Z} $ svn checkout -r {20060217T1530-0500} …
When you specify a date, Subversion resolves that date to the most recent revision of the repository as of that date, and then continues to operate against that resolved revision number:当你指定一个日期,Subversion会在版本库找到接近这个日期的最新版本:
$ svn log -r {2006-11-28} ------------------------------------------------------------------------ r12 | ira | 2006-11-27 12:31:51 -0600 (Mon, 27 Nov 2006) | 6 lines …
You can also use a range of dates. Subversion will find all revisions between both dates, inclusive:
$ svn log -r {2006-11-20}:{2006-11-29} …
如果你只是指定了日期而没有时间(举个例子2002-11-27
),你也许会以为Subversion会给你11-27号最后的版本,相反,你会得到一个26号版本,甚至更早。记住Subversion会根据你的日期找到最新的版本,如果你给一个日期,而没有给时间,像2002-11-27
,Subversion会假定时间是00:00:00,所以在27号找不到任何版本。
如果你希望查询包括27号,你既可以使用({"2002-11-27 23:59"}
),或是直接使用({2002-11-28}
)。
Since the timestamp of a revision is stored as an unversioned, modifiable property of the revision (see the section called “Properties”), revision timestamps can be changed to represent complete falsifications of true chronology, or even removed altogether. Subversion's ability to correctly convert revision dates into real revision numbers depends on revision datestamps maintaining a sequential ordering—the younger the revision, the younger its timestamp. If this ordering isn't maintained, you will likely find that trying to use dates to specify revision ranges in your repository doesn't always return the data you might have expected.
你可以使用时间段,Subversion会找到这段时间的所有版本:
$ svn log --revision {2002-11-20}:{2002-11-29}
…
$ svn log --revision {2002-11-20}:4040
用户一定要认识到这种精巧会成为处理日期的绊脚石,因为一个版本的时间戳是作为一个属性存储的—不是版本化的,而是可以编辑的属性—版本号的时间戳可以被修改,从而建立一个虚假的年代表,也可以被完全删除。这将大大破坏Subversion的这种时间—版本转化功能的表现。