Having been recently stuck with git at work, I had a momentary lapse this morning, and convinced
myself I needed co-located branches (git-style) to work on my game, which is of course under bzr as
any project maintained by sane people should be.
It turns out I didn't, and nobody, ever, does. Here's what to do instead.
Why you think you need it
The most common argument for colo is a source tree for a large compiled project, where you have
hundreds of .o files you don't want to be recompiling all the time.
In our case, we keep the generated player avatars (.png) inside the source tree, which, to be
honest, is not a very brilliant design, but it's also not quite a high priority to fix right now.
Now, based on these arguments, some very clever minds have been hard at work to add colo support to
bzr for the last few years; it's been a core feature since 2.5.0 (2012-02-24).
... but you don't!
Looking at these arguments as someone who understands the bzr model well, a catch soon becomes
apparent: these aren't, in any way, arguments for co-located branches. They are, rather, arguments
for co-located trees, and those bzr already does quite well. (Or rather, it doesn't need to.)
You see, trees only coexist with branches by default. The second greatest argument about bzr is
that it allows you to work your way; and the power that unleashes is often underestimated.
(In case you're curious and haven't yet heard this rant from me, the #1 greatest argument is that
the model is sane and based on a good understanding of version control and real-life workflows,
as opposed to the snapshotty-hashy-hacky of certain other VCSes. But let's not digress too much.)
The how-to
First, put your branches somewhere; a shared repository is preferred to save you lots of space and
(if it's going to be remote) network traffic.
$ cd /somewhere/bzr-repos
$ mkdir my-project
$ bzr init-repo --no-trees my-project
$ cd /where-your-sources-are/my-project
$ bzr push /somewhere/bzr-repos/my-project/trunk
$ bzr branch /somewhere/bzr-repos/my-project/trunk /somewhere/bzr-repos/my-project/my-branch
$ bzr branch /somewhere/bzr-repos/my-project/trunk /somewhere/bzr-repos/my-project/other-branch
2a: Use lightweight checkouts. This is best if the branches are local, and will make your switches
a little faster. Back up your data first; while this won't destroy anything in the history, it
may hose files in the working tree or make your checkout unusable.
$ cd /where-your-sources-are/my-project
$ bzr bind /somewhere/bzr-repos/my-project/trunk
$ bzr reconfigure --lightweight-checkout
2b: Use heavyweight (regular) checkouts. This is better if you're working directly with remote
branches, as you can then work offline; if you're always online, it essentially trades some disk
space for bandwidth, so take your pick.
$ cd /where-your-sources-are/my-project
$ bzr bind /somewhere/bzr-repos/my-project/trunk
$ bzr reconfigure --checkout # probably unnecessary, unless it was lightweight before
3: Happy branch-switching:
$ cd /where-your-sources-are/my-project
$ bzr switch my-branch
$ (do stuff)
$ bzr switch other-branch
$ (do stuff)
$ bzr switch trunk
$ bzr merge my-branch
etc. The relative branch specs work because they're relative to the current branch location, rather
than the working tree.
4: Create new branch:
$ cd /where-your-sources-are/my-project
$ bzr switch -b a-new-branch
5: Delete old branches:
$ cd /where-your-sources-are/my-project
$ bzr switch trunk
$ bzr merge my-branch
$ bzr rmbranch my-branch
Afterword
In fact, since the Bazaar developers are, in fact, a clever bunch, the 2.5.0+ co-located branches
do pretty much exactly this, except the branch storage is hidden inside the .bzr dir of your tree.
So if you still want to do it "the git way", sure, go ahead and do it. In a non-bound branch, bzr
switch -b new-branch will set up your branch and tree for co-located work, and create "new-branch"
co-located to where you are.
The benefit of doing it explicitly, as I describe here (apart from the fact that it worked before
2.5.0, but I'm 8 months too late for that argument), is that you still keep the best of both words:
you can have co-located checkouts, but you can also easily have more than one checkout; for example
(and this would be awesome at work), a "wip" checkout normally bound to the feature branch you're
currently working on, and a bugfix checkout bound to trunk or to your "maintenance" branch. Or, if
you're a gatekeeper, those same two plus a third "master" checkout for merging submissions
(including those from your own feature branches, if you're so inclined).