I never liked CVS—the limitations and design flaws become obvious almost as soon as you start using it—but after years of use it was a familiar model that worked well enough in practice. Then came Subversion. It worked like CVS but fixed the glaring problems, providing atomic commits, the ability to move files and folders, checksumming, revision numbers that represent whole trees, and easier tagging and branching (albeit by shoe-horning them into the tree). Switching was an easy decision. I remained happy with it, especially with the more reliable FSFS backend and the new working copy format. I was aware that Subversion had some problems, but none were too bothersome, and as a solo developer I knew I didn’t need a distributed version control system.
Then I heard about Git when I happened to watch a video of its creator, Linus Torvalds. It had not occurred to me that CVS and Subversion were fundamentally broken. Torvalds is undeniably a smart guy, but he’s also known for his bluster. I’d heard Git mentioned a few times before, usually in the context of it being difficult to use, something only a kernel developer could love. So I was skeptical but interested enough to try it out.
What I found is that Torvalds’s bragging is justified. Learning about Git after using other version control systems is somewhat like learning a new programming language that’s radically different from what you’ve known before. Even if you might not need the more unusual features most of the time, you feel as though your eyes have been opened, your mind expanded.
Beyond just the distributed model, Git’s implementation is beautiful. It stores the repository in such a logical way, using far fewer files and much less disk space than Subversion. Each file, no matter its location in the tree or history is only stored once. The repository is stored in a single .git folder at the top level of your working directory. In addition to its repository, Subversion needs a .svn folder inside each folder of the working directory. The working directory holds two extra files (one for the data and one for the properties) for each file, plus some more file and folders for each directory. Git needs none of these. It’s more efficient, and you don’t need to make sure all your tools have special handling for the invisible .svn folders.
Git’s implementation is compact. It doesn’t rely on a ton of other libraries, and the tar.bz2 file is only 1.1 MB. Compiling Git took only 15 seconds on my Mac, compared to 104 seconds for Subversion.
The user interface is currently a bit rougher than Subversion’s, but it’s not too bad, and some things are actually nicer. Unfortunately, the man pages and manual don’t build out of the box on Mac OS X, so I recommend reading them online, along with the tutorial.
In order to migrate from Subversion I needed to install LWP:
sudo perl -MCPAN -e shell install Bundle::LWP
and a different build of Subversion that included the Perl bindings. With /usr/local/lib/svn-perl in my PERL5LIB I was then able to use the git-svnimport import command, but I found that this didn’t work very well, perhaps because one of my Subversion repositories didn’t use the traditional branches/tags/trunk structure. I had much better luck with:
git-svn init -T <svn-repos> <svn-repos> git-svn fetch
So far I’ve moved two Subversion repositories to Git. Before I move my main development repository I want to write some shell aliases to make it a bit smoother to use, and some scripts to integrate it with BBEdit.