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.
Referring to revision numbers with
an “r
” prefix
(r314
, for example) is an established
practice in Subversion communities, and is both supported and
encouraged by many Subversion-related tools. In most places
where you would specify a bare revision number on the command
line, you may also use
the r
NNN
syntax.
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 and
REV2
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.
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.
COMMITTED
-
The most recent revision prior to, or equal to,
BASE
, in which an item changed. PREV
-
The revision immediately before the last revision in which an item changed. Technically, this boils down to
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.
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 numbers reveal nothing about the world outside
the version control system, but sometimes you need to
correlate a moment in real time with a moment in version
history. To facilitate this, the --revision
(-r
) option can also accept as input date
specifiers wrapped in curly braces ({
and
}
). Subversion accepts the standard
ISO-8601 date and time formats, plus a few others. Here are
some examples.
$ svn update -r {2006-02-17} $ svn update -r {15:30} $ svn update -r {15:30:00.200000} $ svn update -r {"2006-02-17 15:30"} $ svn update -r {"2006-02-17 15:30 +0230"} $ svn update -r {2006-02-17T15:30} $ svn update -r {2006-02-17T15:30Z} $ svn update -r {2006-02-17T15:30-04:00} $ svn update -r {20060217T1530} $ svn update -r {20060217T1530Z} $ svn update -r {20060217T1530-0500} …
Keep in mind that most shells will require you to, at a minimum, quote or otherwise escape any spaces that are included as part of revision date specifiers. Certain shells may also take issue with the unescaped use of curly braces, too. Consult your shell's documentation for the requirements specific to your environment.
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:
$ 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} …
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 datestamp. But datestamps are
stored in the unversioned, modifiable
svn:date
property of the revision (see
the section called “Properties”), so it is possible
for revision datestamps to get out of sequence. Now, most
of Subversion's operations are unaffected by this
situation—after all, the revision number itself is the
primary identifier of each revision. But if the datestamp
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.
Combining the histories of multiple repositories into a
single one (as described in
the section called “Migrating Repository Data Elsewhere”) is the most
common cause of this scenario.