If you're like me, you've used a variety of different version control system over the years. I've used Projector, Clear Case, Source Safe, CVS, and probably something else that doesn't come to mind. However, most of my version controlled files have been for work projects. What I've neglected to version control recently has been my own web site stuff, including both static data and Java code that runs behind the scenes of this site and for another site that I've developed. Sure, the code and data are backed up, but that's no replacement for version control, even when you're the only person touching the files.
I decided to try using Subversion, a (relatively) new version control system that's free and open, and is intented to replace CVS and remedy some of CVS' shortcomings.
It turns out to be pretty simple to set up a local Subversion repository and keep stuff in it. Making the repository network-accessible (for multiple contributors or for yourself working from multiple machines apart from the repository) is a little more work (see the linked information on svnserve and Apache2).
Here's what you need.
Is Subversion Already Installed?
There are a couple of ways to get Subversion. First see if you already have it! Try this:
% which svn
If you have it, the which command will tell you where it's located on your system. The two likely places are /usr/local/bin/ and /opt/local/bin/. You can look for svn there if which doesn't find it. If you have it but which doesn't find it, then you're just missing the $PATH setting.
Get DarwinPorts
If you don't have Subversion already installed, there are a couple of ways to get it. I'll cover how to get it from DarwinPorts, which is what I did because I also wanted to be able to set up a network-accessible repository, which can be done with the DarwinPorts system.
First, download the DarwinPorts installer package from darwinports.org. Get the .dmg disk image and install it.
Next, make sure your shell $PATH variable includes /opt/local/bin where the DarwinPorts stuff lives. In my case, this meant adding this line to my .login file, and then starting a new Terminal session -- of course, the syntax depends on which shell you're using:
setenv PATH ${PATH}:/opt/local/bin
The last step of getting DarwinPorts is to let it self-update:
% sudo port -d selfupdate
Getting Subversion
Now that you have DarwinPorts, you can install Subversion with just one command:
% sudo port install subversion
If you want to make the repository network-accessible, either to yourself or to multiple users, you have a couple of options. One is svnserve, which comes with Subversion, and another is Apache with SSL (see links at end for more information).
Creating a Repository
The first thing you need to do is create an empty repository. This is where Subversion will store your files. In fact, it doesn't store the files in "naked" form that you can look at; it stores them in a database.
You can have multiple repositories. How you organize your files (all in one repository or separated into multiple repositories) is up to you. Pick a good place for your repository -- this is not the place where you will be working on your code -- and create it with this command:
% svnadmin create /full/path/to/repository_dir
For example, I decided to initially keep my repositories under my home directory, which happens to be on an external disk (which happens to currently be an iPod, which serves to emphasize the importance of having a backup strategy for the repository just like any other important data). Following some example I saw somewhere, I created a subdirectory "svn" first, in case I want to put anything outside of Subversion but sort of in the repository area. Here I'm creating separate repositories for (a) my com.bombaydigital Java package source, (b) my Code Vault C++ library, (c) my HexWrench application source, (d) and my bombaydigital.com site files. A repository is logically empty until you import files into it.
% svnadmin create /Volumes/spock/Users/trygve/repository/svn/bombay_java % svnadmin create /Volumes/spock/Users/trygve/repository/svn/code_vault % svnadmin create /Volumes/spock/Users/trygve/repository/svn/hex_wrench % svnadmin create /Volumes/spock/Users/trygve/repository/svn/bombaydigital.com
Importing Your Files
The next thing to do is import some files into the repository. (I'd suggest doing a test first of a dummy repository and few directories and files, which you can exercise with an import, checkout, edit, diff, commit, etc. Once you have a feel for how the directory structure is used, then try it with the directory structure you really want. You can just delete the dummy repository.) What I decided to do was first copy my existing source into a new, clean directory structure, and then import that. Along the way, I found a couple of things to do to get the best results.
- Get rid of any stray folders and files that you don't really want in the repository. Examples are old "CVS" control folders and "Icon?" files, which the Finder normally hides. It seems that "dot" files, hidden from the "ls" command by Unix convention, and hidden from the Finder, are ignored by Subversion, so they're not a problem.
- For text files (e.g. source code), make sure the files have Unix-style line endings. I had some files that had Mac line endings. Unfortunately, in Unix land, programs that are unaware of this will see the file as having no end-of-line indicators. Nothing's corrupted, but when you diff a file everything's on one line, so you can't see the individual diff lines. (I've long since set the CodeWarrior IDE, which I still use for some things, to use Unix line endings for new files.)
The "file://" scheme tells Subversion that the repository is local, on this machine, so Subversion does not need to do this across the network. In all these examples, I'm showing how things work when your repository is on your local machine. If the repository is remote, the URL spec for the repository would look different.
% svn import /full/path/to/import_data_dir/ file:///full/path/to/repository_dir/
The files in the directory you import to the repository in this way will live at the top of the repository.
The svn import and svn commit commands require you to enter a comment message describing your changes. You can either add it on the command line, or if you've set the $SVN_EDITOR variable, Subversion will invoke the editor of your choice, where you can enter it.
% svn import -m "Initial import." /my/import_dir/ file:///my/repository_dir/
By the way, the Subversion tutorials recommend that you place your source one level down in the repository under "trunk", with sibling directories for tags and branches, like this:
project_dir/
branches/
tags/
trunk/
foo.h
That is, you start with empty "branches" and "tags" directories, and your files live under "trunk".
Here's how I imported my Java source:
% svn import
/Volumes/spock/Users/trygve/Documents/Development/source/bombay_java/
file:///Volumes/spock/Users/trygve/repository/svn/bombay_java/
Checking Out A Working Copy
Once you've imported your files, check out a working copy into a sandbox where you can edit them.
This grabs a copy of my "bombay_java" repository and checks it out to a sandbox directory. That is, the "sandbox" directory will now contain a "bombay_java" subdirectory, which in turn has "trunk", which contains the current version of the source code.
% cd /Volumes/spock/Users/trygve/Documents/Development/sandbox/ % svn checkout file:///Volumes/spock/Users/trygve/repository/svn/bombay_java/
Viewing Differences
You can see what you've changed with the svn diff command. If you don't pass any arguments, it'll show you the differences of everything from the current directory on down. So, executed from the top of the tree, you'll see all the local changes you've made that have not been committed back to the repository.
% svn diff
I'm not going to get into more detail on the parameters you can pass to all of these commands. In general, they operate recursively on all folders and files in the current working directory, but you can supply a path to specify a directory or file that you want to refer to rather than the current directory. The svn help command shows all of the commands, and svn help <command> shows the help for a particular command.
Getting Other People's Changes
If someone else changes files in the repository, your local sandbox is no longer up-to-date. To bring it up to date, use the svn update command. (Merge issues may apply.)
% svn update
Committing Changes
When you know your changes are correct and you want to commit them to the repository, use the svn commit command.
% svn commit -m "Fixed bug #42."
Enough Command Line, Give Me A User Interface
No kidding! Well, there's svnX, a free Mac OS X application which does a pretty nice job of things. You point it to your repositories and your working copies, and it gives you a nice interface to your files and all the Subversion commands. It lets you configure the app to use for a visual diff, whether you prefer CodeWarrior, FileMerge (part of the Apple Developer Tools), or TextWrangler.
Useful Subversion Links
- Official Subversion Site: http://subversion.tigris.org/
- DarwinPorts: http://www.darwinports.org/getdp/
- Martin Ott's binary Subversion package: http://homepage.mac.com/martinott/
- Version Control with Subversion: http://svnbook.red-bean.com/
- svnserve info from the book: http://svnbook.red-bean.com/en/1.0/ch06s03.html
- Keeping Your Life in Subversion: http://www.onlamp.com/pub/a/onlamp/2005/01/06/svn_homedir.html
- Bill Bumgarner on Configuring Subversion and Apache2: http://www.pycs.net/bbum/2005/2/17/
- Subversion Cheat Sheet: http://www.abbeyworkshop.com/howto/misc/svn01/
- Single-User Subversion: http://www.onlamp.com/pub/a/onlamp/2002/10/31/subversion.html?page=2
- Making the Jump to Subversion: http://www.macdevcenter.com/pub/a/mac/2004/08/10/subversion.html
- James Duncan Davidson on Subversion and Apache2: http://blog.x180.net/2005/01/subversion_via_.html#more
[3] http://www.technorati.com/tags/subversion
[2] http://blogsearch.google.com/blogsearch?hl=en&q=subversion&b...
[1] Google: "+"mac os x" +subversion"
[1] http://technorati.com/tag/subversion
[1] Google: "ttp://www.google.com/webhp?ie=iso-8859-1"
[1] http://blogsearch.google.com/blogsearch?hl=en&q=subversion+s...
[1] http://technorati.com/search/svn+mac