5

The qrefresh command in the MQ extension don't make sense to me. I'll explain my assumption:

  1. If you don't know on which revision should a certain patch be applied, it have a very little value. You just can't theoretically know what does the rejects mean. And even if there are no rejects on a certain revision, you're not sure the whole revision would compile.
  2. Once you qrefresh a certain patch in your patch queue, you're actually losing the parent of the next patch in the queue. So that without your intervention this next patch is/might be useless.
  3. In order to fix the next patch, you'd better merge it instead of hand-editing the .rej, files. Not just because of the better tools, if you have the original un-qrefresh'ed patch, you have more information, the qrefresh caused you to lose information you actually need in order to make the change you made to the patch meaningful.

Therefor I don't understand why one would ever want to use this command.

A better alternative is, to apply all the patches, then hg update to the parent of the patch you want to change, then, hg revert the working directory to the patch you want to change. Change this patch, commit it to a new revision, and then rebase all the other patches on this new revision.

I simply don't understand when qrefresh is relevant when you're not editing a single patch only. It seems that git's approach (apply the patch to a local branch) makes much more sense than a patch queue.

Am I correct, and I'd better of use rebase? Is there something I missed?

migrated from kiln.se.com due to no response and low view rate

Elazar Leibovich
  • 32,750
  • 33
  • 122
  • 169
  • 4
    I think you need to describe what you think qrefresh does and how you use it. None of what you say resembles how I use qrefresh. – Paul Biggar Nov 09 '10 at 12:45
  • The only use I know of is to change a patch somewhere in the patches stack, and then re-apply all those patches. Do enlight me if I'm missing any other uses. – Elazar Leibovich Nov 09 '10 at 15:12
  • Maybe changing the message line of the top patch when it's not descriptive enough or does not follow the convention you want ? – kriss Nov 09 '10 at 16:21
  • Or storing content in a patch only when you want to. Until qrefresh is actually done you can prefer to create a new patch with qnew -f and drop the whole thing. I do that sometimes. In this case it has not much to do with the patch stack. – kriss Nov 09 '10 at 16:23
  • @kriss, this is the only usage I saw, changing a single patch with no other patches in the patch stack. Otherwise, the best thing to do is to `commit --amend` a new commit with new commit message and then rebase. As I said in the question, if you're going to `qrefresh` a patch and then apply other patches and practically "rebase" them, just commit the whole patches and rebase the commits. – Elazar Leibovich Nov 09 '10 at 16:34

2 Answers2

3

EDIT: after writing the answer below, I stumbled upon the chapter about patches of Mercurial The Definitive Guide. It says more or less the same but is much more detailed that my answer. It also suggest a way (a bit convoluted for my taste, but anyway) to use 3-way merge with patches as the OP was looking for.

Maybe you see mq only as a patch import tool ? That is not my primary use, and for me qrefresh is very useful. The typical use case for me is when I'm working over the top of published repository.

I usually work with a series of patches I'm writing at the same time. I begin by creating a new empty patch. When I believe some (part of a) feature is finished, I qrefresh the top patch to make it include all changes made from patch creation time (or last qrefresh). Then I create a new empty patch and continue writing code that belong to the next patch.

If at a later time when working on another patch I see some change that should be made inside a previous patch (because it logically belongs to it), I do not make the change in the top patch nor create a new patch. First I qrefresh the current patch, then qpop to the previous patch where the changes belong, then make my changes. When it's done I qrefresh again the old patch, then qpush back to where I was working, and so on.

When you work this way, merges are usually very easy and I get nearly no rejects qpoping and qpushing around.

When I belive my full patch series is ready to be published, I qfinish the whole series, and start again with a new empty patch stack.

It is possible to do the same kind of things with rebase, but then you would need feature like git interactive rebase.

The whole point about working with patches is that patches are not yet commited, so can easily be changed, and for that you need qrefresh. Well, I could achieve the same result creating new patches and qfolding them, but there would really be not point doing that, just two commands instead of one.

Now, when patches are external contributions, as a main maintener to my project contributions are included from patches provided by contributors and they never get directly to the repository. They first get inside my main patch stack. If they make changes to the same parts of program I'm working on they are likely to cause rejects (and if so I basicaly do not insert it at all, it is likely to wreak havoc). If they apply to some other part of the program not being currently changed, they basically merge without any problem an can be imported at any point in the patch stack, no obligation to insert them upon a specific revision. But I always read the changes, and quite often I slightly change the contributed code. Then again I use qrefresh to update the external patch to what I belive it should be.

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
kriss
  • 23,497
  • 17
  • 97
  • 116
  • This is exactly what I'm doing, but I occasionally get rejects, and when I do it's very painful to resolve them as I can't do a three-way-merge, since qrefresh dumped the data I need in order to do that. And I see no reason for me to make my life harder. The key problem I see with your post is "The whole point about working with patches is that patches are not yet commited, so can easily be changed", why should you care if a patch is committed or not? Just commit them to a local branch and then rebase at your will, it'll be the same but easier. I still see no reason whatsoever not to do that. – Elazar Leibovich Nov 09 '10 at 15:18
  • Oh, and external patches are not different, if you have patch A against revision R, just apply the patch to revision R and commit it as a new local branch. Same thing as MQ, just with more information, and easier 3-way merge. qrefresh is the same, but loses info, so I see no reason to use it. – Elazar Leibovich Nov 09 '10 at 15:21
  • Obviously you can do without patches. Your problem seems not to be with qrefresh, but with using patches for version management. You pointed exactly the most important point in my answer : there is cases when I **want** to lose informations to keep my repository history simple. In the case of merges, if merge is not easy I'm usually better off without merging at all. Even with 3-way merges, risk is very high I'll do something wrong (like getting the wrong version for part of the lines, as it's a manual process anyway), and the problem is exactly the same with rebase. – kriss Nov 09 '10 at 16:17
  • That's my point. You *should* do without patches, because patches are actually commits in disguise. Just commit the patch and then handle it as you handle unpushed commits, rebase it or strip it away or whatever. Why is it, that if I want to change a commit, I must `qimport` it as a patch? I'd better use a VCS branches, which are the correct way to handle patches. Of course, 3-way merge is not always the best, but it's 100% better then `.rej` files. Even fixing trivial rejects is a confusing, and with 3-way merge it's just easier. I can see no reason to make something which can be easy hard. – Elazar Leibovich Nov 09 '10 at 16:37
  • @kriss, and I'm not trying to convince you, on the contrary, I'm looking for a new insight I might have missed (in this particular case you should not `qrefresh` and then apply, because...). Then again, maybe `MQ` is indeed useful for quickly editing small amount of patches. – Elazar Leibovich Nov 09 '10 at 16:39
  • Oh, and if you want to lose information, just `hg strip` it away. I didn't say `hg strip` is considered harmful ;-) I perfectly agree that you should keep your repository clean. – Elazar Leibovich Nov 09 '10 at 18:03
  • 1
    Personally, I won't use strip, rebase or mq. I believe in an indelible record of work absolutely. That said, mq predates both strip (which is based on mq) and rebase (which is quite new), so back then qref was the only way, and it's still a reasonably popular way to modify things. – Ry4an Brase Nov 10 '10 at 04:23
  • @Ry4an, you should try fossil, which have exactly the same philosophy. But I don't understand how do you keep the main repository clean of "fixed bug #1234", "oops, forgot to add foo.cc, now fixed", "damn, also bar.cc, now really fixed". Those commits will just confuse the future maintainer, and I'd rather they'll be as a branch on my private repo only. (And good answer BTW, `qref` is the plumbing on which the rebase porcelain is based on) – Elazar Leibovich Nov 10 '10 at 04:29
  • @Elazar Leibovich: I do not believe qref is any kind of plumbing for mercurial no git here. There is still a very good reason to use rebase instead of qref I didn't spoke of, this is the one case where I use rebase instead of patches stack. mercurial patches won't store binaries (but repositories will). If you want to put say an image along your sources, you must avoid patches. – kriss Nov 10 '10 at 08:25
  • ... But I still believe rebasing is more error prone than managing a patches stack (tryed both as a day to day practice times ago, now I stick with patches). I never failed to set my patch to the right top of stack patches I wanted to change, I failed not very often but several times setting the right revision for rebasing (both source and dest revision) and created a mess. Those revision ids are just not user friendly, so I copy paste them from hg logs, and sometime I got the wrong line... and I won't feel to tag every revision either. – kriss Nov 10 '10 at 08:34
  • @kriss, I totally agree about unuser-friendliness of the rebase idea. But I have an idea. Why won't `hg qpush` will do the rebase for you! If you push and there are rejects it'll let you do a three way merge (he knows on which revision should the patch be applied on) instead of throwing rejects? This way we'll both be happy! – Elazar Leibovich Nov 10 '10 at 20:27
  • @Elazar Leibovich: yes, it would be nice to have. Sometimes I also consider giving a try to Darcs (http://en.wikipedia.org/wiki/Darcs) that is totally patch based. Looking at how it works would also probably give some light on patch management features in other version control systems. – kriss Nov 11 '10 at 19:19
0

You should pick kriss's answer, s/he explains it all very well, but here's a paper about the software that inspired the patch management feature in both mercurial and git, quilt:

http://www.suse.de/~agruen/quilt.pdf

Ry4an Brase
  • 78,112
  • 7
  • 148
  • 169
  • This software was written with no agile version control like `hg` or `git`. Therefor my strategy was not available then. I'm not sure the author of quilt would disagree with me on my take. – Elazar Leibovich Nov 09 '10 at 16:47