Ed: To make up for the long drought in blogging, I’m gonna try and push out some drafts that I’ve written over the last year or so, but never published. This is the first of them.
CVS really annoys me and I think it’s outlived its usefulness. I’m not familiar with the environment it was built for, but I suspect that that environment existed sometime before I was born. Here are a few things that annoy me about CVS:
- It doesn’t recursively update directories. This means, for example, that if up do cvs up in a working copy, it won’t update nested directories, nor will it create directories which have been added by someone else. You have to do cvs up -dR to get the expected behavior.
- You can’t delete directories. The best you can do is to delete all of the entries from the repository, delete the directory then be careful to not recreate the directory in your working copy. This means that if you do the above (cvs up -dR), you will end up with the empty directories coming back over and over again.
- Its slow. Really, it is. You won’t notice it until you use something else. The fact that it’s written in C does not guarantee that it will be fast.
- It doesn’t understand changesets, only changes to individual files. Most changes I do to code involves little bits of change across several files. CVS has no way of associating those changes with each other. This also means that there is potential to create race conditions, where two people are checking in a series of files at once, which conflict with each other and potentially leave the repository in an inconsistent state. Source code management tools are supposed to help keep a consistent history of the code, not destroy it. This is s serious bug.
- Merging with CVS is a special form of torture. I didn’t realize how painful this is until I started using a tool that is built as if merging is important.
- CVS is difficult to install.
- I can’t work offline. For example, if I’m writing some code on a plane, I have to wait until I land to do my checkins. No matter than I made a bunch of different changes that should all be their own changesets.
For a long time, I thought Subversion was the answer. That was until I tried Mercurial. Subversion offers only incremental improvements on CVS, while Mercurial and similar tools offer new ways of working that have made me more productive.
Subversion certainly has advantages over CVS– it can perform better, it’s web native and makes branching and merging easier. But, they both suffer from the same client-server model. The client server model doesn’t reflect real world practices when it comes to software development.
For example, when I was working on front end code at Technorati (I work on mostly infrastructure stuff these days), there would often be times when I needed to share a bit of work I was doing with another developer so that they could finish up a feature. My code wasn’t ready to go into the mainline of code because it was incomplete.
What we usually ended up doing was copying files across on the development machine. Then when the other engineer finished the feature, they’d check in all of the changes, which has some problems.
The problem is that my work is mixed in with their work. No longer do we have a clean change history.
If we had a tool for easily sharing changesets with each other without committing them to the central repository, we could work much more smoothly and cleanly.
So, enter Distributed Source Code Management systems, of which mercurial is an example. I’m not going to go into their design or history too deeply. Suffice it to say that with DSCMs, each working copy is a full repository and a peer to all other repositories. The peers can share changesets easily.
A result of this architecture is that essentially every change is a branch and every change must be merged. So, merging is really easy. Branching is even easier.
And this is the key difference. Once merging and branching became trivially easy, I found a million uses for it. Suddenly I could branch for every feature without pain. I now find that for a given project I usually have five or six branches lying around (each as their own working copy) and I have no problems keeping them in sync with the main line.
When it comes down to it, I like Mercurial for the freedom it gives me. I’m free to work offline, to branch and merge easily without subjecting others to the same organization and to easily create and share repositories.
If you believe that freedom helps people get their jobs done, then ditch CVS and Subversion.