One of the most vital tools for a programmer is a version control system. My chosen tool is Bazaar, which I use for its flexibility and ease of use. There are other tools out there with various advantages and disadvantages (Git, Mercurial and Subversion to name a few), but I thought I would give an overview of Bazaar.
There are some very good guides already out there, but they can be a bit confusing in places and don't really highlight the advantages of Bazaar clearly. In this post I'll briefly explain what version control is and where Bazaar fits in and then walk you through getting and installing Bazaar on Mac OS X and then getting started using it. I assume some basic knowledge of the command line.
If you already know what version control is then you can skip this section. For those of you who don't, or don't really see the benefits, this is a brief outline. If you've been using Leopard you probably know about Time Machine for backing up your files. Every hour it looks for what has changed since it last backed up, and copies those changes over. This is a very simplified form of version control.
Version control is a means of storing the history of your project. Now version control is often talked about in terms of programmers, but it can be helpful for almost anyone who is working on any project on the computer. While you can undo changes in a document while it is open, you can't go back to before you opened the document. This is where version control comes in.
Let me give a real world example. I've been doing weekly releases of a new application to testers. One week a tester came back with a rather major bug they found soon after they opened the new release. It was fine the week before, so it must've been introduced during the week. Because I'd been using version control I could take the project back to the state it was in at various points during the past week. By doing this I could find out which was the last revision (a 'checkpoint' for your project) that didn't have the bug.
The next useful tool I could use was finding out what files had changed between those versions, and even which lines within those files had changed. After some quick investigation of these changes I found the bug and was able to fix it.
Of course there is another side to version control software and that is helping teams work together. If multiple people are working on a project, there will inevitably be times when two people need to edit the same file at the same time. When this happens you'll get a conflict, there are two versions of this file that you need to merge. Version control software helps ease this by providing tools that warn you of a conflict and help you to resolve them.
I'm going to focus mostly on the former use in this post, though I'll link places where you can read up on resolving conflicts in Bazaar at the end of the post
So what made me use Bazaar? Well let me first make clear that I absolutely hate having to drop down to the command line and avoid it as much as I can. So that will set the scene for my not minding using Bazaar from the command line, which is a unique situation for me. The commands are incredibly easy to learn and use, and the concepts behind it are simple. It is also incredibly flexible and can adapt to almost any workflow.
There are two types of version control system: distributed and centralised. Centralised systems work by having the project hosted in a central location. Users check out a copy of the latest version of the project. They then work on this copy and then commit any changes back to the central location. Distributed systems work by each person having their own copy of the entire history of the project. Any changes they commit are kept in their copy until they choose to share them with someone. This works incredibly well for open source projects.
There are many advantages and disadvantages to both ways of working, but that's for another blog post. What is important is that, unlike most of the other systems out there, Bazaar lets you work in either a centralised or distributed manner, or anywhere in between. And you aren't locked into one way, you can switch between the two incredibly easily.
The last factor is the support behind it. The community of developers and users is one of the most friendly and helpful I've had the pleasure to be part of. It also has the support of Canonical, the company behind the Ubuntu Linux distro so has developers who can work on it full time to improve it.
One thing that has been lacking has been the number of big name projects using it, which has put off some people. But things are slowly changing. Bazaar is used by Ubuntu, the Drupal content management system and recently the MySQL database moved over to using Bazaar. Another project using it that is significant to Mac developers is the Sparkle updater framework.
This combination of ease of use, flexibility and the support available has really cemented Bazaar as my VCS of choice.
While Bazaar does have a few graphical interfaces, none of them are native to the Mac and so look very out of place. I'll be showing you how to use Bazaar through the command line. But first we need to get Bazaar and install it. Bazaar lists installer packages on its download page. If you scroll down you will see installers for OS X 10.5 and 10.4. At the time of writing the current release version of Bazaar is version 1.5, but version 1.6 is well along the way to being released. Download the version for your operating system and then run the installer on the disk image.
Once the installer has finished you can quit it and unmount the disk image. You now have Bazaar installed on your system. The first thing you want to do is tell Bazaar who you are. This is done by using the whoami command like so (replacing with your name and email address):
bzr whoami "John Smith <firstname.lastname@example.org>"
All calls to bzr are in the format "bzr [COMMAND]", in this case the command is whoami. If you want to see who Bazaar currently thinks you are then simply called whoami with no arguments, eg:
bzr whoami Martin Pilkington <email@example.com>
I'm first going to show you how to use Bazaar in a decentralised manner. This is how I use Bazaar and I find it to be ideal if you work alone.
The first thing you'll want to do is create a repository for your project. Two of the main storage entities in Bazaar are repositories and branches. You can have a branch without a repository if you wish, but if you choose to create new branches from this, then the history will be have to copied over, increasing disk usage. Repositories store the history in a central place, so creating new branches is both fast and efficient with disk space.
To create a repository, navigate to the folder where you want the repository to be in Terminal and type the following:
bzr init-repo [REPONAME]
Replacing [REPONAME] with the name of your project. Next, navigate into the newly created repo. To start work we need to create our first branch. You can call this whatever you like, but we'll just call it "trunk" for now, which is a common convention (I personally use "dev" for the name of my main branches but it's entirely up to you what you call it):
bzr init trunk
NB: If you are coming from the git VCS then you will want to take note that in Bazaar branches are just folders. You can find the reasoning behind this here.
Now we want to navigate into trunk. In future you'll want to navigate directly to this directory to do any work with Bazaar. If you've already got a project you want to follow along with, then drag the files into this branch. If not then just create some text files. Our first job in our branch is to perform the initial commit.
There is an important distinction to be made before we go any further. A file may be in your branch while not being in Bazaar. At the moment the files in your branch are not managed by Bazaar. If you were to try and commit now, Bazaar would tell you that there is nothing to commit. We first need to add these files to Bazaar. You will need to remember to do this whenever you add any new files to your project as it is easy to forget about them and just commit.
We use the add command to add files to Bazaar (I said the commands were easy to learn). You can tell Bazaar to add specific files by passing in their filenames like so:
bzr add file1.txt file2.txt
We want to add all the files in the project so we'll call add without passing in any filenames:
Now that we have added all our files to Bazaar, we need to commit them. Committing sets a sort of checkpoint in your project that you can compare with or revert back to. When committing you will also want to set a message so that you (or any team members) have an overview of what changed in that release. We'll just set this message to "Initial commit" as this is our first commit:
bzr commit -m "Initial commit"
You will be told that Bazaar committed successfully and gave this commit a revision number of 1. Each commit is numbered incrementally to allow you to reference commits at a later date.
From time to time you'll want to get information on the current state of the branch and the history of the branch. To get the current state of the files in the branch (whether they are unknown to Bazaar, newly added, modified, deleted etc) you need to use the status command:
This will give you a grouped list of any significant files, ignoring any that are in Bazaar but haven't changed. The next command will show you a history of commits, including who performed the commit, when they committed and what the commit message is. You view this with the log command:
This will show you the full history of the branch. To get the history of a single branch you can pass a revision number in as an argument:
bzr log -r 5
That will get the information for commit number 5. You can also get the history of a range of revisions:
bzr log -r 3..5
That will return the information for commits 3, 4 and 5. One last tool that you will sometimes want to use, is the ability to revert back to a previous state. To do this you use the revert command (be warned, this will erase any uncommitted changes):
bzr revert -r 3
This reverts the state of the files in the your branch to how they were at revision 3. You may also find that you've been editing a file since your last commit and you've made a mess, or found that an idea you had isn't working and you want to go back to the last commit. To do this just call revert without any arguments:
Some people prefer to work in a centralised manner, where their repository is stored on a central server. Bazaar is flexible enough to let you work in this manner as well. First off you need to create your central repository. I am going to assume you have a webserver to which you have SFTP access on which you will store your repository. To create your repository enter the following into the terminal:
bzr init-repo --no-trees sftp://firstname.lastname@example.org/path/to/folder/Repo-Name
You will need to replace 'username' with your FTP login username, 'myserver.com' with the URL of your FTP server, 'path/to/folder' with the path to where you want your repository and 'Repo-Name' with the name you want to call your repository. When you are prompted for your password, type it and press return and Bazaar will create your repository.
The --no-trees argument makes a repository that contains no working trees. This means that there are no files on the server to edit and all of the data is simply stored in the repository's history.
Our next job is to create our first branch. You will do this by using init in a similar way we did with init-repo:
bzr init sftp://email@example.com/path/to/folder/Repo-Name/trunk
Now we have set up our remote server we need to get a local copy of the branch. Even though there is nothing in our branch yet, this will set up the references so that we can commit our files. We will be doing a standalone checkout in this example, but you create a local repository for your checkouts if you wish (this would be useful if you were to switch between centralised and distributed development). To do a checkout, navigate to where you want the checkout to be downloaded to, and then use the checkout command:
bzr checkout sftp://firstname.lastname@example.org/path/to/folder/Repo-Name/trunk
There will now be a folder named "trunk" in the current directory. By navigating into it you can perform all the operation listed above such as status, add, log, revert and commit. If you now add some files to the "trunk" folder we can commit them to the repository online:
bzr add bzr commit -m "Initial commit"
One useful argument you can use on commit is the --local argument. If you pass this in when you commit, Bazaar will commit the files locally instead of directly to the online repository. These will then be put into the online repository when you do a regular commit. This is very useful if you don't want half finished code in your central repository, but need to create commits part way through implementing a big part of your project:
bzr commit -m "My local commit" --local
Below are some really commands and tips that I find really useful when using Bazaar:
Sometimes there are some files you need in your branch folder that you don't want in your repository. This would be fine if it didn't require you to name every other file when performing a bzr add. You can tell Bazaar to ignore files matching certain patterns. These can either be global or project specific. To modify the global ignores open ~/.Bazaar/ignore and enter in your ignore patterns. If you want some project specific ignores then you can create a .bzrignore file in your branch. Here are a set of useful ignores to add for Cocoa projects:
Occasionally you'll perform a commit you didn't mean to make, or make a mistake in writing the commit message. You can undo a commit by using the uncommit command. For example:
bzr commit -m "My colo commit" "Oops, there's a type there" bzr uncommit bzr commit -m "My cool commit"
Say you are using a centralised style of development, but you find you'll be somewhere you won't have network access, such as a plane or a train. You could just do local commits, but if you'll be offline for quite a while you may forget. An easier way is to convert your checkout into a branch and then convert it back to a checkout once you have finished. To do this you use the bind and unbind commands:
bzr unbind "I'm now working on a branch" bzr bind "I'm now working on a checkout again"
If you create a branch you later want to work as a checkout you can use bind with a path to make it a checkout of that path:
bzr bind sftp://email@example.com/path/to/folder/Repo-Name/trunk
Occasionally you'll have a commit that is a major milestone, such as a release version of a piece of software. You can tag these commits with names you can refer to later anywhere you would pass in a revision number:
bzr tag "1.0"
NB: If you are a Subversion users it is worth noting that a tag in Bazaar is simply an identifier you can give to a revision, not a copy of revision.
One advantage of the centralised workflow is that it's easy to have an offsite backup, especially if your server is offsite anyway. This is also useful if you were using two machines and wanting to switch between them (such as a desktop and a laptop). But if you're using a distributed style you won't have this benefit built into your workflow. However you can achieve it using the push and pull commands:
On my desktop
bzr push sftp://firstname.lastname@example.org/path/to/folder/MyBranch --remember
On my laptop
bzr pull sftp://email@example.com/path/to/folder/MyBranch --remember
The --remember argument is a great timesaver. This tells Bazaar to remember the push/pull location entered so every other time you don't need to enter the path again. For example, to move back to your desktop:
On my laptop
On my desktop
This is only an introduction to some of the most commonly used features of Bazaar and shows only two contrasting ways of working. There are many other workflows which you can choose. If you want to find out more you there are many places you can look. The first place should be the Bazaar documentation. The user guide is a series of tutorials for various workflows, but after you know the basics of Bazaar the user reference is far more useful to find out more about each command. There is also a mailing list and an IRC chatroom called #bzr on irc.freenode.net.
Hopefully this (rather lengthy) post will have given you a good overview of how to use Bazaar and why you might want to consider using it as your version control software of choice. However, I do recommend exploring other systems out there to see if they fit your needs better. No one solution is perfect and each excels at different things, what is important is to make a good choice now than have to try and migrate everything at a later date.