O'Reilly FYI

News from within O'Reilly

Be Subversive--10 Subversion Tips to Control Your Code

 
By Sara Peyton
October 2, 2008 | Comments: 1

Is Subversion the right tool? "If you need to archive old versions of files and directories, possibly resurrect them, or examine logs of how they've changed over time, then Subversion is exactly the right tool for you." So write the authors of O'Reilly's Version Control with Subversion, 2nd Ed.--C. Michael Pilato, Ben Collins-Sussman, and Brian Fitzpatrick. And here, these members of the Subversion development team give you their top tips for avoiding the pesky network round-trip, safely moving files and directories with wild abandon, teaching your Subversion client to add certain properties to your files automatically, and more. Check them out.

1. Use status to find out your ... status

With Subversion, if you want to find out what you've modified, you run svn status. This command compares the files in your working copy with those in the Subversion administrative areas (those pesky .svn directories), thus avoiding the necessity of a network round-trip:


  $ svn status 
  D      fish.c
  A      shrimp.c
  M      anemone.c

Note that fish.c is scheduled for deletion, shrimp.c is scheduled for addition, and anemone.c has been modified.

Now, by default, svn status shows only the files that are interesting (like those that have been added, modified, or deleted). If you want to see information about all the files in your working copy, pass the --verbose switch:



$ svn status --verbose
44 23 sally README
44 30 sally INSTALL
44 35 harry trout.c
D 44 19 ira fish.c
A 0 ? ? shrimp.c
M 0 ? ? anemone.c
44 36 harry things/rocks.txt

The first column remains the same, but the second shows the working revision of the item. The third and fourth columns show the revision in which the item last changed, and who changed it.

If you want to know which files will be updated the next time you run svn update, use the --show-updates switch to svn status:


  $ svn status --show-updates --verbose
         *        44        23    sally     README
                  44        30    sally     INSTALL
         *        44        35    harry     trout.c
  D               44        19    ira       fish.c
  A                0         ?     ?        shrimp.c
  M      *        44        32    sally     anemone.c
                  44        36    harry     things/rocks.txt

You can see that the files that will be updated are marked with a *.


2. Remember, you can move things around

I've seen people spend hours in meetings working out the directory structure and file placement of a project, but with Subversion, you can move files and directories with wild abandon:


$ svn move foo.c bar.c
A bar.c
D foo.c

Now bar.c has been scheduled to be added and foo.c has been scheduled for deletion. (This is how Subversion represents a move.


svn commit will send your changes to the server.)

You can even move files and directories on the server by using URLs:


  $ svn move -m "Move a file" http://svn.red-bean.com/repos/foo.c \
                              http://svn.red-bean.com/repos/bar.c

That will immediately move foo.c to bar.c on the server.


3. Tag and branch by copying

In Subversion, branch and tag operations are done as copies:


  $ svn copy -m "Tag rc1 rel." http://svn.red-bean.com/repos/trunk \
                               http://svn.red-bean.com/repos/tags/1.0rc1

You've created a tag of your main line of development (referred to as trunk in Subversion terms). If you want to create a branch instead, copy the trunk line of development into the branches directory--it's just that easy. And in Subversion, tagging and branching are fast too.

In Subversion, tags and branches are just copied paths in the repository tree. By convention, tags live under /tags and branches live under /branches.

Subversion needs only to copy a single directory node to make a copy, which not only is really fast but also takes very little space in your repository--no matter how many files are involved in the branch or tag. The Subversion community calls 'em "cheap copies" for good reason!

You're not limited to tagging all files in the same revision in Subversion: If you need to make a "mixed-revision" tag or branch, you can always copy a working copy to a URL:

$ svn copy -m "Mixed branch." . http://svn.red-bean.com/repos/branch/1.2-mixed

See Branching and Merging for an extensive description of how to branch and tag.


4. "Revert" instead of "delete and update"

Subversion stores a pristine copy of each file in the .svn directory of your working copy, so you can just do this:


  $ svn revert I-made-a-boo-boo.txt
  Reverted 'I-made-a-boo-boo.txt'

That comes in especially handy if you don't have a Net connection at the time.

5. Don't fear your version control system

By default, certain other version control systems that we won't mention (like CVS) translate line endings (from CR [Unix] to CRLF [Windows] and back) and expand keywords (like $Id$) in your files. This is very handy until you commit a binary file to your repository and CVS, in a fit of helpfulness, turns your file into tapioca pudding.

Subversion will never ever ever do anything to your data unless you ask it to.

Let's say that together now:

SUBVERSION WILL NEVER EVER EVER DO ANYTHING TO YOUR DATA UNLESS YOU ASK IT TO.

You can add any binary file to your Subversion repository and not have to do anything special to have Subversion not destroy your file. However, if you add a text file (a .java file or .c file, for example), you may want Subversion to automatically handle end-of-line translation for you. This is done using Subversion properties.

In this case, you will set the svn:eol-style property to native:



$ svn propset svn:eol-style native halibut.c

and then commit your change.

You can teach your Subversion client to add certain properties to your files automatically--see the section on Automatic Properties and their configuration for more information.


6. Log, log, log your log

Subversion's log command gives useful and compact data that is based on an atomic Subversion commit. For example:



$ 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

Outline sandwich fixins.
------------------------------------------------------------------------
r1 | sally | Mon, 15 Jul 2002 17:40:08 -0500 | 1 line

Initial import
------------------------------------------------------------------------

Each log entry shows you the revision number of the entry, the author, the date, the number of lines in the log entry (to aid in parsing svn log's output), and then the log message itself. If you wish to see the paths that changed in your log output, pass the --verbose flag:

    $ svn log --verbose
  ------------------------------------------------------------------------
  r3 | sally | Mon, 15 Jul 2002 18:03:46 -0500 | 1 line
  Changed paths:
     M /trunk/sandwich.txt

Added include lines and corrected # of cheese slices.
------------------------------------------------------------------------
r2 | harry | Mon, 15 Jul 2002 17:47:57 -0500 | 1 line
Changed paths:
M /trunk/sandwich.txt

Outline sandwich fixins.
------------------------------------------------------------------------
r1 | sally | Mon, 15 Jul 2002 17:40:08 -0500 | 1 line
Changed paths:
A /trunk/sandwich.txt

Initial import
------------------------------------------------------------------------

In the above examples, you might have noticed that we're not passing any specific files or directories (called targets) to the log command. If you run svn log without specifying any targets, Subversion assumes that you're referring to your current working directory. Subversion then uses a starting revision of 1, and the working revision of your current working directory as the ending revision. (You can find out what this working revision is by using svn status -v, as we mentioned earlier.)

And now on to a small gotcha: If you commit a change to a file and immediately run svn log, you won't see the log message for your most recent commit. This is because the "working revision" of your working directory has not been updated (committing a file does not automatically update your working directory or any other files). If you run svn update and then svn log, you'll see the "missing" log message.

See http://svnbook.red-bean.com/en/1.5/svn.tour.history.html and http://svnbook.red-bean.com/en/1.5/svn.ref.svn.c.log.html for more information on using svn log.

7. Quickly undo a mistaken commit

Suppose you have a working copy of /trunk and discover that the change you made in revision 303, which changed oyster.c, is completely wrong--it never should have been committed. You can use svn merge to "undo" the change in your working copy*, and then commit the local modification to the repository. All you need to do is specify a reverse difference using svn merge:


  $ svn merge -r 303:302 http://svn.example.com/repos/calc/trunk
  U  oyster.c

Use svn diff to verify that the change is correct, and then commit that to the repository.

For more information, see Undoing Changes.

* That is, restore the latest revision of your repository to its previous state; Subversion will still have the "bad" commit in the repository. Being a version control system, Subversion's job is to remember everything you've ever committed to it.


8. Resurrect deleted items

If you delete a file from your Subversion repository and wish to "resurrect" it into the latest revision of your repository, the easiest way is to svn copy it from a revision before it was deleted into your working copy. Use svn log -v to find the revision where the file was deleted, and then do your copy:


 $ svn copy --revision 807 \
              http://svn.red-bean.com/repos/trunk/perch.c ./perch.c

For more details, see Resurrecting deleted items.

9. Switch to a branch without checking out a new working copy

Because Subversion treats tags and branches as regular paths in the repository, you can't just svn update your working copy to the branch name that you want to start woring on. Enter the svn switch command.

svn switch updates your working copy to mirror a new tree in the repository--say, a branch tree instead of the trunk tree. This is the Subversion way to move a working copy to a new branch.


  $ svn switch http://svn.red-bean.com/repos/branches/vendors-with-fix .
  U  myproj/foo.txt
  U  myproj/bar.txt
  U  myproj/baz.c
  U  myproj/qux.c
  Updated to revision 31.

For more details, see Traversing branches.

10. Browse or even mount your repository

If your Subversion repository is being served up through the Apache HTTP Server (that is, you access it via a URL beginning with http), Subversion gives you a couple of extremely convenient freebies:

First, you can point any web browser to your Subversion repository and navigate your way through the latest revision of your repository.

tips1-top10-browse.jpg

Second, if you're using an operating system that knows how to talk to DAV shares, you can mount your Subversion repository (read-only) on your desktop:

tips2.jpg

tips3-top10-mount.jpg

While this is a convenient way to see the contents of your repository, it's also very useful for sharing files with non-Subversion users.


Copyright © 2004, 2008 Brian W. Fitzpatrick, Ben Collins-Sussman, C. Michael Pilato. Distributed under the Creative Commons Attribution License (v 2.0).


You might also be interested in:

1 Comments

thanks for this... the undo-hint comes to the right time ^^

 

Popular Topics

Browse Books

Archives

Or, visit our complete archives.

FYI Topics

Recommended for You

Got a Question?