Why I like bzr better than git

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.

Instead, after too much struggling with git, I totally turned to bzr now. Why? Now that’s what this post is about.

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.

Hierarchical history

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.

Library Interfaces

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.

Gun safety

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.

Conclusion

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?

One thought on “Why I like bzr better than git

  1. Jakub Narębski

    * Each branch has its own tree::

    You can do the same setup with Git, either by having separate clones, perhaps with shared object database (alternates or symlink), or by using multiple working directories with single repository (with which contrib/worktree/git-new-worktree would help). Nevertheless the multiple branches in single repository, with switching between branches using single working area, was something user’s *wanted* and was created at user’s request, and found very useful.

    * Semantic revision IDs::

    Numerical monotonic (well, partially ordered in the case of nonlinear history) revision identifiers are possible only if there is *central numbering authority*. Which means it is possible only in centralized workflow. Or they are local and cannot be used to communicate with other developers.

    Besides I don’t think that e.g. ‘r16437’ is easier to use than ‘3f5907d’ shortened SHA-1 identifier, or more commonly used ‘HEAD^’, ‘master~2’, ‘v1.2.3-rc1’, or ‘v1.6.4.2-260-g3f5907d’, or ‘@{1}’. Also if you have ‘r15467’ and ‘r15476’ you only know the topological relation between them *if they are on the same branch* (if one is ancestor of the other).

    * Hierarchical history::

    Here I don’t understand what you are talking about writing “With git, all your history is flat.” Take a look at output of “gitk” or “git log –graph” / “git log –graph –oneline”. If you are talking about merge messages, there is always `merge.summary` configuration option, where merge commit contains shortlog(s) of merged branch(es).

    * Serving a branch is uncomplicated::

    You can serve Git repository via HTTP with any web server with a little bit of extra information generated by git-update-server-info, usually run from hooks. Also you have Gitosis third-party tool for easy setting up SSH access. But I agree that it could be easier.

    As to popularity of GitHub: isn’t Launchpad as popular among bzr users?

    * Plugins and Aliases::

    Plugins, stable API, and ever changing repository format (for Bazaar) versus scriptability (suing low level “plumbing” tools provided for that purpose) and stable repository format allowing for independent reimplementations like JGit or Dulwich are design decision. *Both* have their advantages and disadvantages.

    Git has also aliases, with the limitation (needed for scriptability) that you can have the same name of alias as existing Git command. Many commands have configuration which are equivalent to command line options, but the idea to add ability to specify default command line options was discussed but didn’t made it into git (because of difficulties with not breaking existing scripts).

    * Library Interfaces::

    “The main interface of git is the command line interface. It is used both for user interaction and automation […]”. Not true. Well, not entirely true. There is set of git commands (so called “plumbing” commands) which are meant to be used for automation (commands like git-checkout-index, git-update-index, git-diff-files, git-write-tree, git-cat-file, git-symbolic-ref), and there is set of git commands (so called “porcelain” commands) which are meant to be used for user interaction (commands like “git show”, “git log”, “git diff”, “git branch”).

    There is currenly no Git library (the work on libgit2 is stalled), but on the other hand stable repository format and transmission protocols (with place for extending it) allow for *reimplementations* of Git in other languages (JGit in Java, Dulwich in Python, Git# / Managed Git in C#) even if there are no libified bindings for other languages.

    I agree that it would be nice to have Git library.

    * Gun safety::

    “With git I got several times to the point where I just deleted the repository to start over. […] Maybe I am just not experienced enough with git.”

    Yes, you are not experienced enough with git.

    In the case of botched merge, you can always do “git reset –hard ORIG_HEAD” to go back to situation before merge. Also, if you don’t want to commit merge automatically, there is `–no-commit` option…

    * Conclusion::

    If bzr just works for you, there is no reason to swicth to git.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.