Bitbucket is a new social code hosting site for Mercurial (Hg) users, allowing them to view and interact with one another’s distributed revision control repositories. It’s no stretch to say that it’s inspired by the excellent GitHub site for the Git SCM. Being a fan of the simplicity and elegance of Hg, I’ve been waiting for someone to do this for awhile.
Bitbucket is quite young and still in public beta, and they’re working rapidly to make improvements and squash bugs, but they already have plenty of novel features working. One of the coolest ones that caught my eye is support for patch queues a lá Mercurial Queues. I had a little trouble figuring out how Bitbucket handles patch queues at first, at it’s not documented in their help yet, but with the help of developer Jesper Noehr I was able to work it out. So until those official docs are published, I hope this guide can help some folks.
Briefly, What’s a Patch Queue?
I should write an article on mq itself, but the basic idea is that you can maintain a stack of patches against a main repository. This means that you could, for example, work on a few features that build on one another in concise patches instead of a giant one that isn’t cohesive (commit early and often!). If you find while working on UI that there’s a problem with the core feature, you refresh your current UI patch, then pop patches until you’re at the core patch. Fix the problem, refresh the core patch, and push the stack back up to the UI to continue working. In a sense, the patches are like “floating” commits that don’t have to truly committed until you know they’re working, or that you’re not chasing an experimental path. This keeps others on a project from having to sift through excessive, confusing changesets in the version history.
Another case is in projects where patches may be maintained against a changing code base until they can be reviewed (or just finished!). Mercurial’s patch queues allow you to pop all patches, pull in new changes to the underlying repository, and push all the patches back on, with the option to merge them if adjustments are needed. This is called rebasing.
By default, Mercurial Queues just works with a set of patches locally, but it’s possible to actually version control it so others can contribute to work-in-progress patches.
All of this begs for some examples, but I’m going to save that for another article or for the book. From here on, we’ll be looking at how to use patch queues on Bitbucket, assuming you’ve gotten acquainted with mq already.
The Quick Way
Whether you have an existing patch queue to import or you’re starting afresh, this is the shortest path to having your queue set up in Bitbucket:
- Set up your main project repository, if you haven’t already. See Bb’s docs if you need help with that. If you have an existing Mercurial repository, the docs don’t cover that yet. It’s very simple: create a repo on Bitbucket, and push your local repository to its URI. We’ll refer to this main repo as
project-repofor this example.
- Click the ‘patch queue’ button on your project repo.
- Complete the form to create a patch queue. You’ll probably want to name it something like
project-repo-patches. Be sure to check the ‘Omit Series’ box if you already have an existing set of patches you plan to start tracking revisions on.
- Now, all you need to do is
hg qclonethe URL of the new patch repo, something like this:
$ hg qclone https://user [at] bitbucket [dot] org/user/project-repo-patches
qclonecommand checks out a repository and it’s versioned patch queue. If you’ve worked with this before, though, you might be thinking this is backward: normally you’d
project-repo, not the patch queue repo! More on that in a bit.
- If you’re not adding existing patches, you’re done. Just
`hg qnew`and start working on a patch.
`hg qref`when finished with the patch for now, and
`hg qcommit -m "your message"`to commit the work on your patches. To push out your changes for others,
`cd .hg/patches`from the root of the repo you
`hg push`. You should see your changesets and patches show up when browsing the patch queue on Bitbucket.
If you want to use an existing set of patches,
`cd .hg/patches`while in
project-repo-patchesand copy your patches and
seriesfile in from the same location in the branch repo you’ve worked on locally. You should not copy the
statusfile that lives in the
patchesdirectory — it can cause mq to get confused about which patches have been applied, and it will be regenerated when you apply the newly copied patches to
project-repo-patchesas you work with it. Now just run
`hg add`in the
patchesdirectory, and you’re ready to commit and push. From now on, you can use mq normally:
`hg qnew`will take care of
`hg add`’ing new patches, and you can use
qcommitinstead of changing to the
patchesdirectory to commit.
You might notice that the
patches directory has an
.hgignore file pre-defined that will keep some files, like
status, from being pushed out to your shared patch queue repo. This is exactly what gets set up if you run
`hg qinit -c` to start a versioned patch queue on a local repo — Bitbucket has taken these steps for you, as well as setting the path in the patch queue’s
hgrc that Bb needs, so you’re ready to push right out of the box. Note: the
.hgignore isn’t actually being generated right now, which I believe to be a bug and have reported it.
For the Tinkerers: More Detail and an Alternative Approach
If you’ve worked with Mercurial Queues and versioned patch queues before, some things about using them on Bitbucket may seem a little odd at first. I’ll try to explain a little bit about what’s going on. Keep in mind that Bitbucket is still very new and it’s possible that things could change, so do a little poking before following me blindly.
The departures from normal behavior — like the fact that to get a full
project-repo checkout and its versioned patch queue, you
qclone the patch repo instead of the
project-repo — stem from the fact that Bitbucket allows multiple patch queues to be associated with the
project-repo, a feature with tremendous coolness potential. Because of this, Bb doesn’t actually store your patch queue inside of the main project repo as you might do normally for sharing a single patch queue. So, if you were to
project-repo, how is Hg going to know which patch queue you want to pull in with it?
Bitbucket approaches this with a little bit of magic, and we can get some insight into it by peeking at
hgrc files after
qclone’ing a patch repo. So continuing with our example, if we
qclone project-repo-patches, you’d see something like this in
[paths] default = https://bitbucket.org/user/project-repo-patches/.hg/patches
Interesting. Instead of pushing your patches to the root of a patch queue’s repo like you might expect, Bitbucket puts them in
.hg/patches, which seems kind of like a patch queue within a patch queue. Why? Let’s take a look at
project-repo-patches/.hg/hgrc, the main repo’s config file:
[paths] default = https://bitbucket.org/user/project-repo-patches/
So pushing the project repo is going to send to the root of the patch repository. But, if you do some work in the main repo of
project-repo-patches, commit, and push, you’ll find that the changes end up correctly in the main repo,
project-repo, on Bitbucket. Bb is doing some magic to redirect pushes to the root of a patch repo to the “parent” project repo. So, that’s why the patch repo pushes to
.hg/patches. Whew. Sorry if you have to read that a few times.
What About SSH?
So far I’ve been using HTTP in the examples, and there’s a good reason for that. Part of my confusion in intially trying to use patch queues on Bitbucket stemmed from my use of SSH, and Jesper realized that was the problem: the magic described above for
qclone’ing a patch repo to get a full repo and the patches, and having pushes go back to the main repo, is not implemented yet for SSH on Bitbucket. This would lead to a lot of confusion if, like me, you were trying to figure all this out on your own before it’s documented. Thanks to Jesper for his enthusiastic help with this.
SSH is nice because once you’ve given Bitbucket your public key, you don’t need to type your password all the time. It can also be speedier because of compression in the SSH protocol. Armed with the information above, we might try steps like these expecting everything to work over SSH (please note that this does not currently work in my experience):
- Create a new project repository on Bitbucket. Again we’ll call it
- Create a patch queue for it, again
- Now, clone the main repo over SSH (note that you always use the ‘hg’ user for SSH):
$ hg clone ssh://hg [at] bitbucket [dot] org/user/project-repo
- Change to the
.hgdirectory and clone from your patch repository’s special structure:
$ cd .hg $ hg clone ssh://hg [at] bitbucket [dot] org/user/project-repo-patches/.hg/patches
This basically leaves you with a main repo and patch queue with their
hgrc files set up for the same paths that you’d get from the workflow described previously, except this time using SSH. You also get the main repo in a directory named
project-repo as you’d expect, instead of
project-repo-patches after the
qclone approach, which is a bit counter-intuitive. In fairness, there’s no reason you can’t rename the top project directory after the
qclone, once you understand what’s going on.
At least for now, this does not work. You’ll probably get a permissions error when trying to push your patch queue over SSH after setting this up. Jesper noted that he’ll try to get the magic fixed for SSH so that it will work just like HTTP. Hopefully this will one day work as an alternative approach, since SSH is nice, and to me this feels more like a natural Mercurial way to handle multiple patch queues for a project repository than the backwards
All in all, I’m finding Bitbucket really cool so far, and I can see that they’re working hard to improve it every day. A wiki system is in the works (driven by what else but Mercurial versioning), so alongside the already present issue tracker, it should soon provide a worthy and trouble-free alternative for teams thinking about setting up a server to host Trac and a shared Mercurial repository.
Of course, Github has already shown how the social nature of forking and pulling with the help of a web app can make distributed version control more powerful and more fun for individuals, as well as facilitating community in the open source world. It’s fantastic to see the same opportunities come along for Mercurial fans, and I wish the Bitbucket folks best of luck.
By the way, you can find me here on Bitbucket!