Examining History
Prev | Chapter 2. Basic Usage | Next

## Examining History

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 it.

Several commands can provide you with historical data from the repository:

svn log

  Shows you broad information: log messages with date and author information attached to revisions and which paths changed in each revision

svn diff

  Shows line-level details of a particular change

svn cat

  Retrieves a file as it existed in a particular revision number and displays it on your screen

svn list

  Displays the files in a directory for any given revision

### 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 | 2008-05-15 23:09:28 -0500 (Thu, 15 May 2008) | 1 line

    Added include lines and corrected # of cheese slices.
    ------------------------------------------------------------------------
    r2 | harry | 2008-05-14 18:43:15 -0500 (Wed, 14 May 2008) | 1 line

    Added main() methods.
    ------------------------------------------------------------------------
    r1 | sally | 2008-05-10 19:50:31 -0500 (Sat, 10 May 2008) | 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 | 2008-05-21 13:19:25 -0500 (Wed, 21 May 2008) | 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; we used it 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:

- Examining local changes

- Comparing your working copy to the repository

- Comparing repository revisions

#### Examining local changes

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, 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 revisions

If two revision numbers, separated by a colon, are passed via `--revision` (`-r`), 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 one revision to the previous revision is to use the `--change` (`-c`) option:

    $ 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
    …
    $

### Browsing the Repository

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.

#### svn cat

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
    $

#### svn list

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` command with no arguments defaults to the repository URL of the current working directory, not the local working copy directory. After all, if you want 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 previous commands, you can use svn update and svn checkout with the `--revision` option to take an entire working copy “back in time”: [7]

    $ 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 preceding 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, 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
    …

[7] See? We told you that Subversion was a time machine.

Prev | Up | Next
Basic Work Cycle | Home | Sometimes You Just Need to Clean Up