A new users thoughts on mercurial queues

Bill Barry after.fallout at gmail.com
Tue Apr 20 00:28:16 CDT 2010


If you haven't heard of the --mq semi-global option perhaps now is the 
time to look into it. As of hg 1.5 most commands have an option "--mq" 
which acts on the queue repo instead of the main repository.  As of 
right now qinit, qcommit, qrestore, and qsave are all deprecated in 
favor of similar commands with a --mq option.

Matt Rosencrantz wrote:
> I am new to mercurial and I’ve recently discovered mercurial queue’s,
> which are just and awesome idea.  But I can’t help but feel like
> queue’s could be more intuitively integrated.  I had a few thoughts,
> which I realize are likely wrong-headed given that I’m new to all
> this, but I wanted to understand why they might or might not be
> wrong-headed :)  In the ideas that follow P[command] means run that
> command in the patches repository.  Also, since I’m a fresh mercurial
> user, please forgive my incorrect terminology.
>
> By default the fact that the patches directory is version controlled
> is not really used.  In the tutorial on how to use the queues they
> never commit anything, if you do a Pstatus you’ll always see that the
> files are marked as ‘A’.  I think that’s weird.
>
> *  I feel like qcommit should really be more like
> qrefresh; Pcommit [current-patch-file]
> And this new qcommit should optionally take paths in the working
> directory which it would behave as if passed to the embedded refresh
> with -I.  Then qrefresh is something you just don’t normally use at
> all, it’s only for adjusting the set of changes that belong to a patch
> after the fact (if you decided to split a patch say).  This is very
> natural to mercurial users (or at least seems natural to me, a new
> user) who are used to running hg commit.  Now you either commit
> changes to the repo, or to the current patch, either way it looks
> largely the same.
>   
This runs into an issue where you might have wanted to save the queue 
before updating it.
Without taking mq versioning into account, qnew is the mq equivalent to 
commit (and soon qnew will always mean qnew -f bringing the two commands 
closer to each other). When viewed from this perspective, qrefresh is 
the unusual beast that doesn't fit in (it changes history).

I personally think it should be considered a bug for qnew to 
automatically add patches to the mq repository if it exists. Doing so is 
contrary to the explicit nature of the tool. Users should have to call 
hg add --mq instead.

> * then there should be a qrollback that is actually:
> Prollback; Prevert [last-commited-patch-file]
> that puts the most recently commited changes back into your working
> directory, in a way that is very easy to understand for users of hg
> rollback, rollback gets the most recent changes back into your working
> directory and out of any repo.  I would then expect hg revert -a to
> get my working directory back to the state of this patch at it’s last
> committed revision (plus of course all the patches applied beneath
> this one on the stack).  Currently, reverting a file in the patches
> repo doesn’t have the effect I expect, how can you accomplish this?:
>   
>> hg init repo
>> cd repo
>> hg qinit -c
>> hg qnew -m "a test" test
>> hg qcommit -m test1
>>     
hg init repo
cd repo
hg init --mq
echo \.hg|\.mq|status|guards > .hg/patches/.hgignore
hg qnew -m "a test" test
hg ci --mq -m test1
> .hgignore
> series
> test
> committed changeset 0:92a1ae14ab1b
>   
>> echo file1 > file1.txt
>> hg add file1.txt
>>     
> adding file1.txt
>   
>> hg qrefresh
>>     
> file1.txt
>   
>> hg status
>>     
> [[as expected, there's no info here since the patch owns the file]]
>   
>> hg qcommit -m test2
>>     
hg ci --mq -m test2
> test
> committed changeset 1:e435e0b920c2
>   
>> hg -R.hg/patches rollback
>>     
???
thats not something I would expect especially with the queue pushed
> rolling back last transaction
>   
>> hg -R .hg/patches revert --no-backup .hg/patches/test
>>     
eww; you have just gotten mq and the patch repository out of sync; I 
imagine a qrefresh might fix it but still this seems wrong
maybe (instead of the last two commands):
hg qpop
hg -R .hg/patches strip tip
(strange, why doesn't strip have --mq available; I think it would be 
nice if just about every command had it?)
hg up --mq
(might not be necessary, I don't remember the semantics of strip that well)
hg qpush
> reverting .hg/patches/test
>   
>> hg status
>>     
> [[the patch doesn't own file1, it's empty, the repo doesn't own file1,
> it's not committed, why is status empty?]]
>   
This is because of the mq data stored in your revlog. As far as your 
repository is concerned, it is still committed because the queue is 
still pushed. A rollback and revert of the patch queue isn't doing what 
you are thinking. It will not change anything about any of the pushed 
patches, only the serialized representations of them.
> note that a qrevert command would only be helpful in the rare cases
> when you used qrefresh to edit the current patch without committing.
>   
mq has too many commands as it is. Adding more only serves to further 
confuse users who are learning how to work with it (as I am afraid you 
are apparently demonstrating here [no offense intended]).
> * It would be nice if there was a default patch created on qinit.  It
> would just be empty and it would pick up content whenever you did
> qcommit (or more unusually qrefresh).  You could rename it if you
> wanted.  Whenever you delete the last patch in your patches repo
> (either via qrm or qfinish) we’d just create a new default patch, so
> there’s always some patch on the stack.  This would make queues look
> more analogous to normal mercurial operation, you would create a repo,
> start working, commit to either a patch or a repo revision, work some
> more, etc.  Starting a new patch would feel more like creating a
> branch.
>   
Again, you should be preferring qnew over qrefresh. It will never hurt 
to have more patches than less and you can always fold them together 
when you near completion.

I view qrefresh as a shortcut to qnew+qpop+qfold. As such I tend to use 
it sparingly because I prefer to work my patches out over many 
iterations and only when it nears completion fold them down into 
finished changesets. I regularly build up patch queues of 50+ items 
which I then fold down to 3-5 patches before finishing. It is and always 
will be easier to fold patches than it is to split them.
> * Couldn't each patch file in the patches repo have a header that
> tracked the revision the patch applies to? (call it baserev).  Then
> qpush could always trigger a 3-way merge between {baserev, baserev +
> patch, working directory} (if working directory is not a decendent of
> baserev, or if the patch is new and therefore has no baserev, we just
> apply the patch on the working directory as best we can).  
It is there and called parent; I am not sure if it is used to merge the 
queue as it applies (it wasn't back when I last really studied the mq 
codebase while writing attic). Attic does do this btw and it is slow. 
Doing this slows attic down nearly 10x.
> This would
> eliminate the current sort-of-byzantine recommended merge dance.  It
> would work for merging between patches and re-basing.  
Can't you already rebase patch queues? I thought that was a bug that was 
fixed not too long ago... I was under the impression that this worked:

hg qpush -a
hg pull --rebase
(brings up merge windows)
hg qpop -a
(refreshes each patch where needed so that they push back on cleanly)
> Whenever qpush
> merges it should update the embedded revision in the patch file. so
> after a qpush when re-basing, after resolving merge conflicts, you’d
> end up doing a qcommit (or likely you would have the qpush -M
> “message” option that is mentioned at the bottom of the current wiki
> tutorial page).  Again this is using the modified version of qcommit I
> mentioned above.  This way the best thing will happen for most users
> automatically.
>
> In all of this I'm mainly interested in using queues to solve
> entangled working directory problems and building up my own patches
> while frequently re-basing against some shared repository somewhere.
> I know there are other cases I haven't thought about.
>   
This is one of the major use-cases of mq, but perhaps you would be 
better suited to pbranch. Admittedly it is a bit more confusing up front 
(I think the examples could use a bit more work) but as soon as you 
start groking it, it suddenly all just makes sense and you wonder why 
you were screwing around with a versioned mq repo so hard.
> Anyway, I’d really appreciate any responses, like I said I’m new, and
> so I suspect there are a lot of issues I don’t understand and I really
> appreciate your insights.
>
> Matt
> _______________________________________________
> Mercurial mailing list
> Mercurial at selenic.com
> http://selenic.com/mailman/listinfo/mercurial
>
>   

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial/attachments/20100419/23bba0f7/attachment.htm>


More information about the Mercurial mailing list