Using Bazaar on Subversion projects

Overview

bzr-svn lets developers use Bazaar as their VCS client on projects still using a central Subversion repository. Access to Subversion repositories is largely transparent, i.e. you can use most bzr commands directly on Subversion repositories exactly the same as if you were using bzr on native Bazaar branches.

Many bzr-svn users create a local mirror of the central Subversion trunk, work in local feature branches, and submit their overall change back to Subversion when it is ready to go. This lets them gain many of the advantages of distributed VCS tools without interrupting existing team-wide processes and tool integration hooks currently built on top of Subversion. Indeed, this is a common interim step for teams looking to adopt Bazaar but who are unable to do so yet for timing or non-technical reasons.

Installing

Windows

The Windows installer already includes bzr-svn and the required dependencies. You can get the installer from: http://wiki.bazaar.canonical.com/Download/

Ubuntu

If you’re running Ubuntu, the easiest way to get bzr-svn is via apt-get. To get the latest version, you’ll probably want to add the Bazaar PPA to your apt sources. For instance, if you’re using Hardy, you would add:

deb http://ppa.launchpad.net/bzr/ppa/ubuntu hardy main
deb-src http://ppa.launchpad.net/bzr/ppa/ubuntu hardy main

Once your system is configured correctly, you can simply run:

sudo apt-get install bzr-svn

Getting started

In general, working against a Subversion repository with Bazaar and bzr-svn, is identical to working against a Bazaar repository. As a result, you typically want to follow the guidelines for working with Bazaar branches. For instance, you’ll probably want to set up a shared repository to make branching locally operate faster. Please consult the Bazaar User’s Guide for more information about general Bazaar usage.

Supported URL Schemes

bzr-svn supports using the same URLs that you normally use with a standard Subversion client:

  • http:// or https://
  • svn://
  • svn+ssh://
  • file://

For http:// and https:// URLs, it does this by participating in the remote repository discovery process, and probing the remote repository to check if it’s a Subversion repository. bzr-svn will send an OPTIONS request and check to see if version-control is listed.

The svn: revision specifier

When working with Subversion branches, it can be handy to refer to a revision using Subversion’s native revision number. You can do that by using the svn: revision specifier. For instance:

bzr log -r svn:2

svn diff style patches

The typical way of formatting a patch, is to use bzr send. bzr-svn adds an extra format option --format=svn to specify that the generated diff matches the output that would be generated by running svn diff. This format is automatically used if the submit branch parameter of bzr send points to a Subversion repository.

The details

Merging trunk to your feature branch

When interacting with a Subversion repository, merging trunk into your feature branch should be avoided. Merging trunk into your feature branch will record a commit that alters how the new trunk revisions are introduced onto your branch versus how they appeared on trunk. For instance, take the following example of creating a feature branch called “myhacks”:

../_images/myhacks-before-merge-with-parent.png

The feature branch introduced some new changes, and along the way, trunk had a new revision (F) introduced. So trunk was merged into myhacks to bring it up-to-date with trunk. As a result, we now have the following commit graph:

../_images/merge-with-parent.png

The problem arises when reintegrating your changes back into trunk. You might be tempted to push your changes into trunk since your branch will have the same content. However, look at the commit graph from the perspective of the myhacks branch:

../_images/graph-view-from-myhacks.png

The push command says “make the destination branch’s commit graph look like my branch’s commit graph.” As a result, pushing your branch Bazaar will reorder the commits on trunk to reflect how they got introduced in the feature branch. In this case, you would see Bazaar copy revision B of trunk, introduce C, D, and E. Then it would fold F into G, and introduce H. That’s very different graph than the current trunk.

Technically, Bazaar is taking the correct action, but it introduces a social problem: the commits in the Subversion repository will be reordered as well. If you have commit mails, then you’ll see emails generated for the new revisions introduced in the feature branch, as well as for commits that were merged from trunk to the feature branch. This is disruptive from a developer point of view. Therefore, newer versions of bzr-svn won’t allow you to push a branch that reorders commits by default.

Instead, use merge to reintegrate your changes back to the mainline. Using merge, won’t alter the order of the commits on trunk. It will simply introduce a new commit, just like merging in Subversion. Here’s is the resultant commit graph when using merge instead:

../_images/safe-way-to-merge-myhacks.png

Note that no commits were changed on trunk. Only a single revision I was introduced to bring in the changes from the myhacks feature branch.

Note

If you want to allow bzr-svn to reorder commits, you must set append_revisions_only to False in $HOME/.bazaar/subversion.conf (or $APPDATA\Bazaar\2.0\subversion.conf on Windows) for the branch that you’re pushing to. For example:

[3458f17e-d762-4919-9a8e-96d024cedc1e]
locations = file:///Users/johndoe/test/
append_revisions_only = False

Rebasing

If you still need to track the current happenings on trunk, and want to see the individual commits you’ve done as individual commits in Subversion, then you’ll want rebase to bring the trunk revisions into your feature branch.

Rebase will unroll your changes, bring in the revisions from trunk, and replay your revisions on top of the most recent commit. For instance, let’s say the myhacks has the following commit graph relative to trunk:

../_images/rebase-before.png

After rebasing, C, D, and E would be introduced as C', D', and E', but based on the tip of trunk instead:

../_images/rebase-after.png

Once you’re ready to reintegrate your changes into trunk, you would use push to push the individual changes back into trunk. Using this technique will not reorder commits. Rebasing imposes it’s own limitations on sharing, so read up on the topic before you attempt to rebase a shared branch.

Additional metadata

When bzr-svn pushes data to the project’s Subversion repository, it will set some revision properties. If the project would rather not see that data, or you’d rather operate in stealth mode, the use bzr dpush instead of bzr push. You lose a bit of bzr-related information this way, but it’s more friendly to your upstream consumers. In general, the metadata is small and most commit mail scripts will ignore it. If the upstream project doesn’t mind having it then use push versus dpush.

If the project is using some tool to view the repository via the web, you may want to have them filter bzr-svn’s metadata from the view. This can easily done by filtering out everything that starts with “bzr:”.

Here is the typical metadata pushed to Subversion via bzr-svn:

bzr:revprop:branch-nick : trunk
bzr:revision-id : john@szakmeister.net-20090916084307-j1nfdpa2qo7yo1f7
bzr:revno : 3
bzr:user-agent : bzr2.0rc2+bzr-svn0.6.4
bzr:file-ids : A    2@3458f17e-d762-4919-9a8e-96d024cedc1e:trunk%2FA

bzr:mapping-version : v4
bzr:committer : John Szakmeister <john@szakmeister.net>
bzr:repository-uuid : 3458f17e-d762-4919-9a8e-96d024cedc1e
bzr:root : trunk
bzr:timestamp : 2009-09-16 04:43:07.528000116 -0400
bzr:base-revision : svn-v4:3458f17e-d762-4919-9a8e-96d024cedc1e:trunk:2

The information here just helps bzr-svn track some extra information that Bazaar users would typically want (bzr:committer, bzr:revprop:branch-nick, bzr:revision-id, etc). A couple of properties, like bzr:mapping-version, provide some miscellaneous information to bzr-svn. In this case, bzr:mapping-version tells bzr-svn what technique it used to map svn revision numbers into Bazaar revision ids.

Lightweight checkouts

bzr-svn’s version of lightweight checkouts are actually Subversion working copies. This means you can interact with you Subversion working copy using Bazaar and bzr-svn!

In this mode, some of the limitations listed below (about keywords, eol style support, and versioned properties) don’t apply since your are working with a native Subversion working copy. However, there is still a limitation from a UI perspective. While bzr-svn will respect keywords, properties, etc., you can’t manipulate them directly through Bazaar. Another limitation, is that operations touch the repository more than necessary. For instance, bzr st in a Subversion working copy requires network connectivity.

The potential upside to all of this, is the ability to use tools like qbzr and others against your Subversion working copy.

Limited keywords support

Anything marked with svn:keywords will remain unexpanded in Bazaar. This is due to the lack of keyword support in Bazaar, and that there is no concept of versioned properties in Bazaar.

Bazaar, however, does support the notion of content filters. The catch is that you need to set up a rules file and say which kinds of files you want to enable svn keyword expansion on. For example, if you want to enable svn keyword expansion of LastChangedDate and Id on your .c files, you’d add this to your rules:

[name *.c]
svn-keywords = LastChangedDate, Id

Limitations of bzr-svn

Bazaar and Subversion are different tools with different capabilities so there will always be some limited interoperability issues.

Versioned properties

Subversion has a concept of versioned properties that is not currently present in Bazaar. This means bzr-svn cannot set any versioned properties, such as: svn:keywords, svn:eol-style, and svn:mime-type.

bzr-svn, will however, preserve versioned properties that are already present on the files.

No tracking of file copies

Currently, Bazaar does not track file copies. As a result, bzr-svn is unable to tell Subversion that a file was copied from another versus being completely new. The result is that you lose the history on the new file. In practice, copying files and intending to keep history is rare anyways. Bazaar does track renames, and this will appear correctly in Subversion and retain the history.

End-of-line style handling

This requires eol-style handling in Bazaar, which is still experimental. All files marked with the svn:eol-style as being “native” will be in LF format locally, since that’s how Subversion stores them. CRLF, LF, and CR will all be in the correct format.

No automatic import of svn:ignore

This requires a modification to Bazaar, to allow querying repositories for the ignores list. A potential solution has been proposed.

No support for svn:externals

Bazaar has been working on the concept called “nested trees” maps well to the concept of externals. Nested trees is still a work in progress, and needs to add support for pointing at the tip of the branch before it can be mapped cleanly to externals.

See the bzr-svn web page, http://wiki.bazaar.canonical.com/ForeignBranches/Subversion, for the current list of constraints.

Footnotes

[1]The default format in Bazaar 1.x was not a “rich-root” format. A rich-root format allows bzr-svn to store extra metadata about the Subversion repository.