Using Mercurial Queues and bitbucket.org

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:

  1. 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-repo for this example.

  2. Click the ‘patch queue’ button on your project repo.

    Adding a Patch Queue in Bitbucket


  3. 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.

  4. Now, all you need to do is hg qclone the URL of the new patch repo, something like this:
    $ hg qclone https://user [at] bitbucket [dot] org/user/project-repo-patches

    The qclone command 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 qclone the project-repo, not the patch queue repo! More on that in a bit.

  5. 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 qclone’d and `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-patches and copy your patches and series file in from the same location in the branch repo you’ve worked on locally. You should not copy the status file that lives in the patches directory — 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-patches as you work with it. Now just run `hg add` in the patches directory, 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 qcommit instead of changing to the patches directory 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 qclone the 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 project-repo-patches/.hg/patches/.hg/hgrc:

[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):

  1. Create a new project repository on Bitbucket. Again we’ll call it project-repo.
  2. Create a patch queue for it, again project-repo-patches.
  3. 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
  4. Change to the .hg directory 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 qclone.

Bitbucket Rocks

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!

Hi Ches, Thanks for the

Hi Ches,

Thanks for the nice write-up! I might paraphrase some things from your post on the official docs later on.

I thought I’d clarify something about the alleged “magic” we’re doing wrt/ the .hg/patches/ path; from ‘hg help qclone’:

Source patch repository is looked for in /.hg/patches by default. Use -p to change.

The patch directory must be a nested mercurial repository, as would be created by qinit -c.

It’s default behavior for MQ to look for patches in .hg/patches/, so we’re not doing anything honkey-donkey there. And regarding your comment about pushing a patch queue into a patch queue, that’s not entirely correct either. The ‘.hg/patches/‘directory is a hg repository in itself, yes, but there are no more repositories under that. This is the directory where you will find your
patches, ‘series’, etc.

I agree that the behavior might seem a bit confusing at first, alas I must largely attribute this to MQ itself. The only magic we’re doing is telling you to qclone your patch repo, and not the main one, and as you point out, this is because several patch queues are allowed for one repository.

In fact, let me clarify that a bit further. Say you create a patch queue to A, called B, then qcloning B will give you a copy of A under the name B, and the actual patch queue will reside in B/.hg/patches/. This is because you can then keep up to date with A’s changesets, and keep your patch queue intact. This just makes it a lot easier to rebase your patches, and it also means that MQ will have something to apply the patches onto locally.

Article ϲarrément plaisant

Article ϲarrément plaisant !!!

Sujet carrémеnt intéressant

Sujet carrémеnt intéressant

Un fort remerciemеnt à

Un fort remerciemеnt à l’administrateur de ce sitе internet

Incroyɑblement attraϲtif,

Incroyɑblement attraϲtif, selon moi ϲe poste intéresserait ma meuf

And regarding your

And regarding your comment about pushing a patch queue into a patch queue, that’s not entirely correct either. The ‘.hg/patches/‘directory is a hg repository in itself, yes, but there are no more repositories under that.

Yep, didn’t mean to imply that it actually is a patch queue within a patch queue, just kind of feels redundant the first time. I’ll try to reword the article a bit there.

Say you create a patch queue to A, called B, then qcloning B will give you a copy of A under the name B, and the actual patch queue will reside in B/.hg/patches/. This is because you can then keep up to date with A’s changesets, and keep your patch queue intact.

This is essentially the part where it clicks once you put all the pieces together, and it’s really nifty. Ordinarily you probably wouldn’t think about keeping up with multiple patch queues for a centralized repo — you’d put one patch repo directly inside A’s .hg/patches, and everyone qclones A. Bitbucket’s approach makes it really easy to think about actually forking other people’s patch queues, and tracking the same base repository without really having to think about it. Of course there’s no reason you couldn’t normally do this with hg, but it’d be a lot harder to keep track of.

They have a thorough everyday

They have a thorough everyday updated databases ofused vacation trailers for sale alongside with
with their total descriptions (pictures
integrated).

Article très caƿtivant

Article très caƿtivant

Poѕte vгaiment plaisant

Poѕte vгaiment plaisant

That´s a new point of

That´s a new point of view,interesting…sometimes things are not working as predicted….

bye,
Sara

Post new comment

The content of this field is kept private and will not be shown publicly.
By submitting this form, you accept the Mollom privacy policy.