Many people I know are using git as VCS and like it a lot. Although I used git in the past and still use it from time for time for some open source stuff, I was never a part of the hype on promoting git and bashing bzr.
Supporting multiple workflows
One cannot deny that git is very successful in what it does. But let’s take a look back in the history how git has been started all. At first it has been written as a management tool for the Linux kernel development. The first goal was to create a fast distributed version control system, which was met very early. Back then it was only usable for technical aware people (see the man page, it still calls git the stupid content tracker).
Later on, git has been improved a lot and became easier to use. But what stayed was the Linux centric view of development. Therefore, git has good support for a distributed workflow as it is used in Linux kernel development, but nothing more. So if you want to use git productively in a team you have to adopt this workflow, which is entirely based on a hierarchy of pull operations. The main developer pulls from fellow developers, those again pull from below and so on.
With bzr instead, you have the choice how you want to work. There is more than one workflow and it is possible to use them all. Of course you can do the same with bzr as with git, setting up a pull-based distributed system. But bzr also supports working in centralized ways. You can bind your local branch to another remote branch. Every time you commit, it will automatically be submitted to the bound branch. This is also sometimes called a checkout. A branch contains the full history which will be available for local operations after pulling from remote. Additionally there are lightweight checkouts, where the branch is not in the same location as the checkout and therefore requires access to the branch for almost all operations. But compared with branching a lightweight checkout is a very fast operation and requires less network traffic.
Supporting centralized workflows makes it easier to convert existing projects and infrastructures from CVS/SVN to bzr. There is not much training required for the developers as it works nearly the same as their old system after initial setup.
Each branch has its own tree
As we are talking about workflows this is the next point. A
git clone can fetch a lot of different branches. All live in the same directory and if you want to view another one you need to use
git checkout <branchname>. You cannot compare files in branches in a simple way with external tools, you always have to use
git diff (or rather
git difftool) which operates on temporary files which means you are unable to edit files right there.
Always seeing only one branch at a time is quite a limited view on the code management infrastructure. Also, if you already made local changes on a branch it might be impossible to switch to another as the changes do not apply there. Therefore you need to hide your changes with
git stashbefore switching the branch.
With bzr this is totally different. The main point is that bzr only operates on branches. So you only get one branch when you use the
bzr branch command. If you want to also have another branch, use the command again on another branch URL. By default, every branch has its own history storage and associated checkout. If you want to save some disk space, you can create a shared repository with
bzr init-repo in the directory which is supposed to hold the branches. If applicable, all branches will share the same storage in this directory.
Having the branches side-by-side makes it a lot easier to compare branches and make edits based on diff reviews. As branches will always be available, you never have to switch between them. Therefore, you do not have to
stash changes in bzr just to view another branch and you will never forget to apply stashed changes after you switched around.
Semantic revision IDs
With git, revisions are identified with a SHA1 checksum. I totally dislike this approach, as it takes all semantics out of the identifier. First of all, the revision id is very long. Yes, you can shorten it to the relevant part only. But still this is not human-readable and cumbersome to type. Bzr just uses incrementing numbers, which is much easier to recognize and remember.
With checksums as revision identifiers you loose any time information. For example if a developer using git tells you, a bug has been fixed in df3b2e, the latest release is f9a4c2 and HEAD is 6ec4b8 you have no idea at all if this revision would be in this release or how long this has been fixed. Now, with bzr this would be: a bug has been fixed in r367, the latest release is r314 and HEAD is r371. So you know immediately that this fix cannot be part of the latest release and is relatively new on the branch.
For more information read on at Understanding revision numbers in the Bazaar User Guide.
With git, all your history is flat. If you do a merge you see a message in the log that you did a merge and which HEADs where merged. But you cannot see what exactly has been merged.
Using bzr, merges always create a hierarchy. That means if you work on a feature in a seperate branch and you finally merge it, you will see the merge message in the log, and below that all the commit you did on the other branch. Your history is a hierarchy of changes This means you have all the changes for this feature grouped together which makes it a lot easier to figure out why a specific commit has been done.
There is also a nice example in the Bazaar User Guide.
Serving a branch is uncomplicated
Did you every try to let others pull from your git branch? Either you need to run git-daemon or run a even more complicated setup using ssh. As a side note, I believe that’s why github became so popular, sharing a repository with git is just too difficult to set it up yourself…
With bzr, just drop the branch in your htdocs directory of the webserver and give others a HTTP URL. No special configuration required, no extra daemon. Bzr only needs to transfer regular files for read-only access. Also works the same with FTP. Easy as 1,2,3. But of course you can still run a standalone bzr server or ssh-based setups for better performance and to allow others to write as well.
Plugins and Aliases
One of the most powerful features of bzr is the modularization. Plugins can define new commands and or extend existing commands with new functionality. And there are lots of plugins available, e.g. graphical user interfaces using GTK+ or Qt, import/export to other VCS systems, statistic tools and more. This keeps the main codebase small and clean, but still you can get all the functionality and features you want.
Additionally, you can redefine the meaning of every command in bzr using a simple configuration file. Want always to see the diff in the log message editor? Just add ci = ci –show-diff. You can also add new commands that way. Customize it the way you like so it fits in your workflow.
As we talk about custom commands and aliases, we have a main problem of git. The main interface of git is the command line interface. It is used both for user interaction and automation which is why you have to cut back on that and cannot customize it the way you are able with bzr.
As bzr is written in python it offers a module named bzrlib, which can be used for integration into IDEs, Editors and other tools. Bindings for other languages exist as well.
Most important for me is safety of the commands I am executing. With git I got several times to the point where I just deleted the repository to start over. Happened a lot of times as I tried to merge stuff together, as git assumes by default it did the right thing and implicitly commits merges without user review. Maybe I am just not experienced enough with git, but with bzr it is way more harder to shot yourself in the foot.
So much for my experiences and the things I like about bzr. I know that some of you will now comment that I could this and that in various ways with git… But the point for me is: if I obviously couldn’t figure out how to do it with git and I had the just works experience with bzr, why should I ever go back?