Bazaar
Posted by at 15:06 on 14 Jun 2009. There are ? Comments

Bazaar is a fairly new distributed version control system gaining wide use, especially because of it being the default VCS for Launchpad.net, a project originally started by Canonical for Ubuntu and other free / open source projects. It is similar in function to git, the DVCS originally created to manage the Linux kernel after licensing issues with the system that was in use up until 2005, but with a more familiar interface for users that are familiar with Subversion. In fact, if you regularly use svn you will find switching to Bazaar to be incredibly easy. This is exactly what I have done recently for my personal projects, and I plan to convince you to do the same.

First, a little background. I have been involved with software development for over ten years and I've used many different methodologies and version control systems to keep track of everything, starting with no version control on small personal projects to my current job where we have many developers working on a huge codebase managed in a central Subversion repository with various branches and tags. One thing you quickly learn is that while version control may seem like overkill for a small project you are doing to learn or scratch an itch it becomes an absolute necessity as your project gets bigger or you add developers.

<p>Water droplets on a leaf after a storm
</p>

Water droplets on a leaf after a storm

(~)
CameraCanon Eos 50D
Date05 April 2009 at 02:53
Exposure ModeAperture Priority
Exposure Time1/80 seconds
Aperturef/9
ISO Speed800
Focal Length105 mm
MeteringPattern
FlashOff

Because of my current employment I use Subversion every day. I know and understand how svn works, and I am well aware of its limitations which we regularly curse in the office, but while keeping in mind those limitations it is a very nice system to manage source development. One of the major limitations is that branching is difficult and requires copies of information inside the central repository. In fact, there are quite a few limitations based around the difficulty of branching and having multiple repositories or workflows that most centralized revision control systems have. Distributed version control systems like bzr and git are supposed to help solve these issues, which is why I have started to experiment with bzr.

A distributed version control system is one in which there is no need for a central repository (though most can use a central repository style workflow). Instead, anybody can create a branch from any published repository and even publish their own or send their changes up the chain to be incorporated back into the original. This fundamentally changes the way that development can be done because it allows anyone to publish their changes extremely easily, stay up to date with the parent branch in one command, and have version control in their local branch before having to commit any changes anywhere. You shouldn't underestimate the incredible usefulness of this.

Example Setup

I'll assume if you are reading this that you have at least had a little experience with centralized version control systems like CVS or Subversion. Using Bazaar is very, very easy so let's get started. For this example we will create a small Python project, make several revisions, then publish it. I will show how to both use a separate branch and how to bind the branch to the parent branch so that bzr works almost exactly like svn. If you don't yet have Bazaar installed, you should do so now. Ubuntu users can do the following or simply click to install:

sudo apt-get install bzr

Once installed we can create a new repository. Let's make our project directory and the simple Python application for the initial checkin.

mkdir hello
cd hello
touch hello.py

Now open hello.py and edit the file to look like the following, a simple "Hello, world!" that should be familiar.

#!/usr/bin/env python
 
"""
A simple Hello World application.
"""
 
print "Hello, world!"

Creating a Branch

Back in the terminal we can now make our project directory into a versioned branch and add the hello.py file under version control. This is done using the init and add commands, followed by committing the changes to the local repository.

bzr init
bzr add .
bzr status
bzr commit -m "Initial checkin of hello project"

You should immediately recognize some of these commands; in fact other than the init command you could replace 'bzr' with 'svn' and all the commands would be just as valid assuming you are working in a Subversion checkout. Just like with Subversion the commands mean the same thing - we are adding files, looking at the status of the repository (it should show which files have been added but not yet committed) and then we commit with a message describing the change. Congratulations, you now have a working local Bazaar repository for your project and can keep track of all changes.

You can try it out by modifying hello.py or adding other files like a README, for example you could try to modify hello.py to look like the following:

#!/usr/bin/env python
 
"""
A simple Hello World application.
"""
 
name = raw_input("Enter your name: ")
print "Hello, %s!" % name

Now you can use all the familiar commands from svn:

bzr diff
bzr commit -m "Ask user for a name and print hello to them instead of the world"
bzr log

But wait, what if you made a mistake? Luckily bzr allows you to undo the last commit without having to manually undo it or use the weird merging backwards trick from svn:

bzr uncommit

Publishing Branches

Now, while having a local branch is nice, it isn't exactly easy for anybody else to get at the code or work on the code, so we need to publish it. There are several ways to do this, and they all involve the concept of pushing and pulling from a parent branch. When you push to a parent branch you are merging all your local history of changes to the parent, similar to how a single Subversion commit works but with all your local commits. One way to push a branch is via SSH, for example. You can push via SSH to a location on a server that is accessible via HTTP so that others can branch:

bzr push sftp://user@host:path

This will publish your local branch to the host you specify above. If it is accessible via e.g. HTTP then anybody in the world can create their own local branch from your now published branch. This is done using the branch command.

# Create a local branch from a published branch
bzr branch http://host/path
 
# Update the local branch to the latest code
bzr pull
 
# Commit local changes to the local branch
bzr commit -m "Commit message"
 
# Push local commits to the parent branch
bzr push

Branches vs. Checkouts

In order to easily support centralized version control system style development Bazaar allows a branch to be bound to a particular parent, causing it to become a checkout. When you commit to a checkout it is committed directly to the parent before being committed locally, essentially acting like svn commit does. At any time you may bind a local branch to a checkout or unbind a checkout back to a local branch. It is also possible to do a checkout directly from a published branch. Doing all three is easy:

# Create a checkout of a remote branch via ssh
bzr checkout sftp://user@host:path
 
# Change the checkout to a local branch
bzr unbind
 
# Change the local branch back into a checkout
bzr bind sftp://user@host:path
 
# Update from the parent branch
bzr update
 
# Commit directly to the parent branch
bzr commit -m "Commit message"

Notice that a checkout still pulls all history to your local machine so that you can use diff, log, blame, etc without having access to the parent branch. Sometimes this can pull a lot of data so you might want an svn-style checkout that only contains the latest revision. You do lose the ability to use commands that require access to the history when not able to connect to the parent branch, just like svn, but you are still able to commit locally until you can push up to the parent again.

# Create an svn-style checkout without full history information
bzr checkout --lightweight sftp://user@host:path
 
# Commit locally in a checkout when e.g. offline
bzr commit --local -m "Commit message"

Shelving Changes

Sometimes you will be working on a change that touches several files in several places, and something comes up where you need to push a quick fix in a file you have already modified. Using svn you could save the diff, revert, push your quick fix and then apply the diff again, or create a branch, but either way it is a complete pain. With bzr you could create a quick branch and push the change, but that requires copying files and a couple more commands than are really necessary. Bazaar provides a shelf for just such a scenario, where you can selectively shelve changes temporarily until you are ready for them to be in use again. For the scenario above you could essentially do:

# Shelve current work
bzr shelve --all
 
# Edit files for quick fix and commit
bzr commit -m "Quick fix for foo"
 
# Restore your current work
bzr unshelve

What About Git?

Git is another great distributed version control system, but here are some reasons I prefer Bazaar:

  • Identical syntax to Subversion that makes switching easy
  • Written in and easily extended with Python
  • Launchpad.net provides excellent free services around Bazaar

There is actually a great list of reasons for using Bazaar on the Bazaar site.

Conclusion

I am not alone when I say that distributed version control is the future, and it seems each day some other large project moves to either Bazaar or Git. Bazaar is an amazingly useful and simple tool, especially if you come from a Subversion background and want to jump into distributed development or are just plain tired of svn branching headaches. I highly recommend using bzr for your next project and finding out for yourself if it works as well for you as it has for me!

Comments

blog comments powered by Disqus