Your Subversion repository is like a time machine. It keeps
a record of every change ever committed, and allows you to
explore this history by examining previous versions of files and
directories as well as the metadata that accompanies them. With
a single Subversion command, you can check out the repository
(or restore an existing working copy) exactly as it was at any
date or revision number in the past. However, sometimes you
just want to peer into the past instead of
going into the past.
There are several commands that can provide you with
historical data from the repository:
Generating a list of historical changes
To find information about the history of a file or
directory, use the svn log
command. svn log will provide you with a
record of who made changes to a file or directory, at what
revision it changed, the time and date of that revision, and,
if it was provided, the log message that accompanied the
commit.
$ svn log
------------------------------------------------------------------------
r3 | sally | Mon, 15 Jul 2002 18:03:46 -0500 | 1 line
Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | Mon, 15 Jul 2002 17:47:57 -0500 | 1 line
Added main() methods.
------------------------------------------------------------------------
r1 | sally | Mon, 15 Jul 2002 17:40:08 -0500 | 1 line
Initial import
------------------------------------------------------------------------
Note that the log messages are printed in
reverse chronological order by default.
If you wish to see a different range of revisions in a
particular order, or just a single revision, pass the
--revision (-r) option:
$ svn log -r 5:19 # shows logs 5 through 19 in chronological order
$ svn log -r 19:5 # shows logs 5 through 19 in reverse order
$ svn log -r 8 # shows log for revision 8
You can also examine the log history of a single file or
directory. For example:
$ svn log foo.c
…
$ svn log http://foo.com/svn/trunk/code/foo.c
…
These will display log messages only
for those revisions in which the working file (or URL)
changed.
If you want even more information about a file or
directory, svn log also takes a
--verbose (-v) option. Because Subversion
allows you to move and copy files and directories, it is
important to be able to track path changes in the filesystem,
so in verbose mode, svn log will include a
list of changed paths in a revision in its output:
$ svn log -r 8 -v
------------------------------------------------------------------------
r8 | sally | 2002-07-14 08:15:29 -0500 | 1 line
Changed paths:
M /trunk/code/foo.c
M /trunk/code/bar.h
A /trunk/code/doc/README
Frozzled the sub-space winch.
------------------------------------------------------------------------
svn log also takes a --quiet
(-q) option, which suppresses the body of the
log message. When combined with --verbose, it
gives just the names of the changed files.
Examining the details of historical changes
We've already seen svn diff
before–it displays file differences in unified diff
format; it was used to show the local modifications made to
our working copy before committing to the repository.
In fact, it turns out that there are
three distinct uses of svn
diff:
As we've seen, invoking svn diff with
no options will compare your working files to the cached
“pristine” copies in
the .svn area:
$ svn diff
Index: rules.txt
===================================================================
--- rules.txt (revision 3)
+++ rules.txt (working copy)
@@ -1,4 +1,5 @@
Be kind to others
Freedom = Responsibility
Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$
Comparing Working Copy to Repository
If a single --revision
(-r) number is passed, then your
working copy is compared to the specified revision in the
repository.
$ svn diff -r 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 3)
+++ rules.txt (working copy)
@@ -1,4 +1,5 @@
Be kind to others
Freedom = Responsibility
Everything in moderation
-Chew with your mouth open
+Chew with your mouth closed
+Listen when others are speaking
$
Comparing Repository to Repository
If two revision numbers, separated by a colon, are
passed via --revision (-r), then the two
revisions are directly compared.
$ svn diff -r 2:3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 2)
+++ rules.txt (revision 3)
@@ -1,4 +1,4 @@
Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
Everything in moderation
Chew with your mouth open
$
A more convenient way of comparing a revision to the
previous revision is to use the --change (-c):
$ svn diff -c 3 rules.txt
Index: rules.txt
===================================================================
--- rules.txt (revision 2)
+++ rules.txt (revision 3)
@@ -1,4 +1,4 @@
Be kind to others
-Freedom = Chocolate Ice Cream
+Freedom = Responsibility
Everything in moderation
Chew with your mouth open
$
Lastly, you can compare repository revisions even when
you don't have a working copy on your local machine, just by
including the appropriate URL on the command line:
$ svn diff -c 5 http://svn.example.com/repos/example/trunk/text/rules.txt
…
$
Using svn cat and svn
list, you can view various revisions of files and
directories without changing the working revision of your
working copy. In fact, you don't even need a working copy to
use either one.
If you want to examine an earlier version of a file and
not necessarily the differences between two files, you can use
svn cat:
$ svn cat -r 2 rules.txt
Be kind to others
Freedom = Chocolate Ice Cream
Everything in moderation
Chew with your mouth open
$
You can also redirect the output directly into a
file:
$ svn cat -r 2 rules.txt > rules.txt.v2
$
The svn list command shows you what
files are in a repository directory without actually
downloading the files to your local machine:
$ svn list http://svn.collab.net/repos/svn
README
branches/
clients/
tags/
trunk/
If you want a more detailed listing, pass the
--verbose (-v) flag to get output like
this:
$ svn list -v http://svn.collab.net/repos/svn
20620 harry 1084 Jul 13 2006 README
23339 harry Feb 04 01:40 branches/
21282 sally Aug 27 09:41 developer-resources/
23198 harry Jan 23 17:17 tags/
23351 sally Feb 05 13:26 trunk/
The columns tell you the revision at which the file or
directory was last modified, the user who modified it, the size
if it is a file, the date it was last modified, and the item's
name.
Warning
The svn list with no arguments
defaults to the repository URL of the
current working directory, not the
local working copy directory. After all, if you wanted a
listing of your local directory, you could use just plain
ls (or any reasonable non-Unixy
equivalent).
Fetching older repository snapshots
In addition to all of the above commands, you can use
svn update and svn
checkout with the --revision option
to take an entire working copy “back in time”
[8]:
$ svn checkout -r 1729 # Checks out a new working copy at r1729
…
$ svn update -r 1729 # Updates an existing working copy to r1729
…
Tip
Many Subversion newcomers attempt to use the above
svn update example to “undo”
committed changes, but this won't work as you can't commit
changes that you obtain from backdating a working copy if
the changed files have newer revisions. See the section called “Resurrecting Deleted Items” for a
description of how to “undo” a commit.
Lastly, if you're building a release and wish to bundle up
your files from Subversion but don't want those
pesky .svn directories in the way, then
you can use svn export to create a local
copy of all or part of your repository
sans .svn directories. As
with svn update and
svn checkout, you can also pass the
--revision option to svn
export:
$ svn export http://svn.example.com/svn/repos1 # Exports latest revision
…
$ svn export http://svn.example.com/svn/repos1 -r 1729
# Exports revision r1729
…