*   \   &   ©   |   /   * *   \   &   ©   |   /   * *   \   &   ©   |   /   * *   \   &   ©   |   /   * *   \   &   ©   |   /   *

Terse Subversion Tutorial

Pretty much assumed you already know version control (at least in theory) and are just looking to get started with Subversion (SVN) specifically.

This tutorial will be done assuming all your SVN hosting is done locally, with file:/// URL’s. It’s trivial to translate it for a remote repository hosting situation — just replace “file:///svn/” with “http://myserver.com/svn”

Excellent hosting provider TextDrive does subversion, or roll your own: see Exposing SVN w/ Apache+DAV.

Install Subversion

Mac OS X

  • get universal binaries here
  • or use DarwinPorts/MacPorts: port install svn
  • there’s also a decent GUI frontend, although I don’t like it: svnX

Windows

Create a repository

Find a place for all your repositories to live. On my Mac I put it in ~/Library/svn; on my FreeBSD server it is /usr/local/svn. Use whatever you’re comfortable with. I make a symlink from “/svn’ to it so that I can just type stuff like “file:///svn/” no matter where I am which is what I’ll reference the repo as from now on.

We’re going to setup a repository for an amazing new app called paint!

cd /svn
svnadmin create paint

Import a repository

Get out of the svn dir, which is where all the svn database metadata is. Go to where all your current paint code lives:

svn import . file:///svn/paint

Now it’s all imported, but you need to check out a working copy to start making changes.

Working with the repo

Go to where you do your code business. I use ~/dev.

svn checkout file:///svn/paint paint

Get in the habit of syncing with the main repository before you start adding your latest and greatest features. ‘svn update’ (or just ‘svn up’) brings your working copy in sync with the main repository.

cd paint
svn update

OK, now we can hack. Change stuff liberally. Or add some files:

touch awesome-thing.c
svn add awesome-thing.c

Send all your changes back to the repo:

svn commit -m "just hacked some code and added this really awesome thing"

You can omit -m and it’ll pop open your EDITOR and you can fill in the change description it in there. But that’s super annoying, so use -m

Conflict Resolution

Two days later…

How’s yer hacks doin’? Pop out a list of changed files:

svn status

Want to see actual changes to the code, or even compile a patch?

svn diff
svn diff > my-awesome-changes.diff

(you’d import that with

patch -p0 < my-awesome-changes.patch
, by the way)

Updating & resolving conflicts

When you run

svn update
you’ll see something like:

$ svn update
C  foo.c
Updated to revision 31.
$ ls
foo.c
foo.c.mine
foo.c.r30
foo.c.r31

C is for conflict. U is for updated, A is for added, that kind of thing. Here’s the master list of codes:

A -- scheduled to be added
C -- in state of conflict (resolve it)
D -- scheduled to be deleted
M -- file has been modified
R -- scheduled to be replaced (delete-then-add)
? -- file not under version control(1)
! -- file is under version control but is missing or incomplete
~ -- versioned file has been replaced by directory (?)
I -- file is ignored (this only shows up if you use --no-ignore, obviously)

This conflict will produce several files: a “quasi-merged” foo.c, with markers delineating the diff sections, your original version, the previously synced version (r30) and the newly synced version (r31). You won’t be able to commit your sweet changes until this conflict is resolved!

So what do you do? I pop open open all of them in TextMate, God’s gift to text editing, like so:

mate foo.c*

Mostly you only need to really look at foo.c, which will have “conflict marker” showing contested areas stuff like this:

<<<<<<<<<
print "this is the debug info *I* put here"
=====
print "this is what the other dude changed this line to that's conflicting."
>>>>>>>>>

Pick your favorite line of code, delete the markers, and continue. This is kind of ghetto, really. Perforce is way nicer, very “visual” and interactive, showing both copies and then asking you which one you want or if you want to edit it. SVN figures you can tough it out.

Then when you’re done say:

svn resolved foo.c

Feel free to safely continue hacking, commiting, etc.

Externals and other SVN properties

You can give directories myriad properties. Use svn propget ., svn propedit ., or change the . to a dir, like vendor which I use a lot on Rails apps

  • svn:ignore — good for ignoring log files, tmp files, distro tarballs, local config files, etc.
$ svn propget svn:ignore .
tmp
pkg
  • svn:externals — you can specify remote SVN repositories that’ll get pulled in automatically!
$ svn propget svn:externals vendor
rails    http://dev.rubyonrails.org/svn/rails/tags/rel_1-1-6/
radius   svn://rubyforge.org//var/svn/radius/tags/rel_0-5-1/radius/
redcloth http://code.whytheluckystiff.net/svn/redcloth/tags/RELEASE_3_0_4/

Pluses & minuses of svn:externals…

  • + always have the latest code
  • - always have the latest code
  • - slows down all svn operations, although you can do “—ignore-externals’ and it won’t check
  • - huge pain if a remote repository is down and you forget to always type —ignore-external

A great workaround is to use Piston, which is an, uh, external externals manager. It checks out the code and you have to explicitly update it with a “piston update” which is nice when there are externals you want that don’t use tags, like small plugins and the like. Piston also lets you use externals with svk, which I’ll discuss more below.

sudo gem install -y piston

(TODO: Piston website link and sample usage.)

Branches & tags (copying & merging repos)

Standard svn repo structure:

/branches  <-- forks of the main trunk, for bugfixes or experimentation
/tags   <-- copies of main code that have been "tagged" as a release (e.g. 0.6, 0.7)
/trunk <-- main development, sometimes called "head"

Generally this is done using the bulky ‘svn smerge’ command to copy one repository, then one manually merges changes from the branch into the trunk when needed. svnmerge.py facilitates auto-merging changes.

Automated branching & tagging can be achieved using a small utility like sc or SubversionAutomation . This is life changing for any large project, can’t recommend it enough.

More advanced ish and cool shell scripts

  • shell scripts to autogenerate stuff
  • ...

Using SVK for more decentralization

SVK is a layer on top of svn designed to facilitate “offline” hacking of another repository, allowing you to still grab updates from that repository and maintain your own local branch.

This wouldn’t be super necessary if svn allowed you to branch from a remote repository, but alas.


GETTING STARTED

svk has a rich command line interface that can be somewhat daunting at
first. the following few commands are all you’ll need for day to day
operation.

svk mirror

First, you’ll need to mirror a remote repository. This sets up a local copy of that repository for you to branch from, merge to and otherwise poke at. The local path is sometimes called a “depot path.” # This command sets up the mirror directory for your local # mirrors of remote repositories svk mkdir //mirror svk mirror svn://svn.example.com/project_x //mirror/project_x

svk sync

When you’ve set up a new mirror or want to get some work done without a network connection, sync your local repository with upstream repositories. svk sync //mirror/project_x

svk copy

After that, it’s easy to copy remote branches to create local branches. (svk branches are simply directories, just like Subversion branches.) # This command sets up a directory for your local branches. # Local branches can’t live inside mirrored paths svk mkdir //local svk copy //mirror/project_x //local/project_x

svk checkout

When you want to get some work done, you can checkout a working copy to make local changes. cd ~/svk-checkouts svk co //local/project_x

svk add, svk delete and svk move

As you work on the files in your working copy, feel free to add new files, delete existing files and move files around. cd ~/svk-checkouts/project_x svk add Changelog svk move badly_named_file.c well_named_file.c svk delete .README.swp

svk commit

When you’re done, just commit your changes to your local repository, whether or not you have network. If you commit to a mirrored path, rather than a local branch, you’ll need to be able to access the path’s upstream subversion server, but the commit will be sent to the server instantly. svk commit

svk pull

Life doesn’t stop when you make a local branch. From time to time, pull down changes from the upstream repository. svk pull //local/project_x

svk push

When you’re ready to share your changes with the world, push them to the upstream repository. svk push //local/project_x

To see a full list of svk’s commands, type svk help commands. For help
with a specific command, just type svk help command.

The svk wiki (http://svk.elixus.org) is a great place to find the
latest svk tips, tricks and updates. If you run into trouble using svk,
the wiki’s the right place to start looking for help.

Web stuff:

  • Trac is a nice python webapp frontend for subversion repositories, with issue management and wiki stuff builtin. Kinda beefy though.
  • There’s a Ruby clone of Trac that I like too, Collaboa. It’s got some cool features but is still under dev and was a pain to install. Also there is a Collaboa fork called Retrospectiva which is much more featureful, but development is a bit crazy at the moment (sup’ing almost always results in breakage)



Comments

Commenting is closed for this article.