Mercurial - Working with Queues similar to Shelves

2019-04-04 14:28发布

问题:

I've recently started working with MQ as I like the idea of working on isolated patches and committing without affecting the repo until the changeset is refined enough. Before that, I used to work with Mercurial's shelves extension, but found it a bit unstable. What I'm still trying to figure out in MQ is how to keep patches separate from each other and apply them in no particular order, and across different branches. Here's my normal flow -

1. Start working on a new patch:

hg qnew fix-bug-1234 -m "fix bug 1234"
# do some work
hg qrefresh

2. Get a new feature/bug to work on:

hg qpop fix-bug-1234
hg qnew some-feature -m "implement feature X"
# some work on feature X (perhaps in a different branch)
hg qrefresh

3. At this point, I'd like to get back to working on bugfix, and put aside the feature work. I thought it's as simple as:

hg qpop some-feature
hg qpush fix-bug-1234
# wrap up bug fix
hg qfinish fix-bug-1234
# get back to work on feature

However, MQ seems to always use the latest patch created in the series, and apply it regardless of the qpop/qpush command I'm using. I should note that the files I work on are completely separate as well (though they can sometimes be the same).

Am I missing something here? Should I be using hg qqueue for this? Thanks.

回答1:

You could use guards. They allow you to maintain an ordering of patches without rearranging your series file, and selectively apply only a subset of patches, still in a stack-ordered fashion.

An example in your case would be:

hg qnew bugfix
# ..hack hack..
hg qrefresh
# want to switch over to working on some feature now
hg qpop
hg qnew feature
# ..hack hack..
hg qrefresh

At this point, you're in a situation where patch feature comes before bugfix in your stack. Now you can use guards to select one or the other, and switch between the two:

hg qpop -a
hg qguard feature +featureguard
hg qguard bugfix +bugfixguard

If you want to work on feature:

hg qselect featureguard
hg qpush
applying feature
now at: feature

If you want to work on bugfix:

hg qpop -a
hg qselect bugfixguard
hg qpush
applying bugfix
now at: bugfix

Note that since you selected the positive guard bugfixguard, MQ leap-frogged over feature (because it's positive guard was different than the one selected) and applied the patch bugfix instead (which did match the selected guard).

Some useful tools when working with guards are hg qseries -v, which will display a G instead of the usual U for a guarded, unapplied patch, and hg qselect -l which will display the guards associated with each patch.



回答2:

  1. Execute hg qpop -a to remove all patches from the stack
  2. Execute hg qpush --move some-patch to apply "some-patch" without applying whatever other patches may be before it in the patch stack


回答3:

No, you aren't missing anything. The mq extension does make a pretty strong assumption that patch queues are linear. If you're going to be creating multi-patch features/fixes then qqueue would work… But if your features/fixes are just single patches and you want to be able to apply one with out applying the others, it might be easier to just re-arrange .hg/patches/series (which stores the order that patches will be applied).

I do this (and hand-editing patches) enough that I've got a shell alias:

alias viq='vim $(hg root)/.hg/patches/series'

Alternately, if you don't mind applying multiple patches at the same time, you could use qgoto:

$ hg qser
0 U bug-1234
1 U feature-4321
$ hg qgoto feature-4321
$ hg qser
0 A bug-1234
1 A feature-4321