Is `qrefresh` considered harmful? - mercurial

The qrefresh command in the MQ extension don't make sense to me. I'll explain my assumption:
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.
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.
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

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.

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

Related

Incorporating external changes using Mercurial and TortoiseHg

I'm looking for advice on how best to organize my repository to handle outside changes. And, I have a simple user question on creating a branch in TortoiseHg. This is my first time setting this sort of thing up, so I'm having trouble figuring out the most straightforward way to handle it.
I have a website set up on a service. The theme we're using is based on one of their examples. Occasionally, they'll update the theme we're based on. And, most of the time, I would like to incorporate most of those changes.
The part that is tripping me up is that I don't necessarily want to incorporate all of their changes. So, is the correct way to do it to create two branches? One that is canonical version, straight from them, containing only their edits? And the other is our release branch, that we merge in only portions of their changes?
Will the canonical branch persist? Or, does it come into existence only when they do a new dump, and then I do a manual merge back into my release branch with the changes I want to incorporate?
If it's persistent, is there some way to use TortoiseHg to create the branch back at the root? Or, do I need to dig into the command-line syntax to do that? I know this is a one-time thing for this project. But, I'm looking for advice on how to do this in other software situations, where I want to go back to an earlier version to make a patch. I'm sure there's a tutorial for exactly this situation, but I wasn't able to come up with the correct search phrase to find it. At least, not using TortoiseHg.
If upstream theme is also version-controlled (in any SCM, supported by Mercurial), two long-term branches with grafting some subset of changesets from VENDOR to MY is, naturally, fast and easy way (another possible solution is MQ-patches on top of branch with vanilla theme, but it's slightly harder way)
If original theme not versioned, you can just grab sources from time to time, edit (incorporate own changes, remove unwanted) and commit this own changeset into single-branch repository
is there some way to use TortoiseHg to create the branch back at the root?
I can not recall or find (with quick-search) nice & obvious way to create branch in GUI-way (i.e. big button on toolbar "Branch"), but you can create branch at commit stage (anyway, branch doesn't exist while at least one changeset in this branch isn't committed). In order to create branch, starting from <some old> changeset, you have:
Update to <some old> changeset (RClick - Update...)
Commit (without changing anything), but in commit dialogue use "Branch" button on commit-toolbar (see 1) in order to change old branch-name to some new (see 2)

What to do instead of squashing commits in Mercurial

I've got my IDE set to commit locally every time I save anything. I'd ideally like to keep an uncensored record of my idiot fumblings for the rare occasions they may be useful. But most of the time it makes my history way to detailed.
I'd like to know a good strategy to keep that history but be able to ignore it most of the time. My IDE is running my own script every time I save, so I have control over that.
I'm pretty new to Mercurial, so a basic answer might be all I need here. But what are all the steps I should do when committing, merging, and reporting to be able to mostly ignore these automatic commits, but without actually squashing them? Or am I better off giving up and just squashing?
Related question about how to squash with highly rated comment suggesting it might be better to keep that history
Edit - My point here is that if Mercurial wants to keep all your history (which I agree with), it should let you filter that history to avoid seeing the stuff you might be tempted to squash. I would prefer not to squash, I'm just asking for help in a strategy to (in regular usage, though not quite always) make it look as much as possible like I did squash my history.
You want to keep a detailed history in your repo, but you want to have (and be able to export) an idealized history that only contains "reasonable" revsets, right? I can sympathize.
Solution 1: Use tags to mark interesting points in the history, and learn to ignore all the messy bits between them.
Solution 2: Use two branches and merge. Do your development in branch default, and keep a parallel branch release. (You could call it clean, but in effect you are managing releases). Whenever default is in a stable state that you want to checkpoint, switch to branch release and merge into it the current state of default-- in batches, if you wish. If you never commit anything directly to release, there will never be a merge conflict.
(original branch) --o--o--o--o--o--o--o (default)
\ \ \
r ... ... --r--------r (release)
Result: You can update to any revision of release and expect a functioning state. You can run hg log -r release and you will only see the chosen checkpoints. You can examine the full log to see how everything happened. Drawbacks: Because the release branch depends on default, you can't push it to another repo without bringing default with it. Also hg glog -r release will look weird because of the repeated merges.
Solution 3: Use named branches as above, but use the rebase extension instead of merging. It has an option to copy, rather than move outright, the rebased changesets; and it has an option --collapse that will convert a set of revisions into a single one. Whenever you have a set of revisions r1:tip you want to finalize, copy them from default to release as follows:
hg rebase --source r1 --dest release --keep --collapse
This pushes ONE revision at the head of release that is equivalent to the entire changeset from r1 to the head of default. The --keep option makes it a copy, not a destructive rewrite. The advantage is that the release branch looks just as you wanted: nice and clean, and you can push it without dragging the default branch with it. The disadvantage is that you cannot relate its stages to the revisions in default, so I'd recommend method 2 unless you really have to hide the intermediate revisions. (Also: it's not as easy to squash your history in multiple batches, since rebase will move/copy all descendants of the "source" revision.)
All of these require you to do some extra work. This is inevitable, since mercurial has no way of knowing which revsets you'd like to squash.
it should let you filter that history to avoid seeing the stuff you might be tempted to squash
Mercurial has the tools for this. If you just don't want see (in hg log, I suppose) - filter these changesets with revsets:
hg log -r "not desc('autosave')"
Or if you use TortoiseHg, just go View -> Filter Toolbar, and type in "not desc('autosave')" in the toolbar. Voila, your autosave entries are hidden from the main list.
If you actually do want to keep all the tiny changes from every Ctrl-S in the repo history and only have log show the subset of the important ones, you could always tag the "important" changesets and then alias log to log -r tagged(). Or you could use the same principle with some other revset descriptor, such as including the text 'autosave' in the auto-committed messages and using log -r keyword(autosave), which would show you all non-autosaved commits.
To accomplish your goal, at least as I'd approach it, I'd use the mq extension and auto-commit the patch queue repository on every save. Then when you've finished your "idiot fumblings" you can hg qfinish the patch as a single changeset that can be pushed. You should (as always!) keep the changes centered around a single concept or step (e.g. "fixing the save button"), but this will capture all the little steps it took to get you there.
You'd need to
hg qinit --mq once to initialze the patch queue repo (fyi: stored at \.hg\patches\)
hg qnew fixing-the-save-btn creates a patch
then every time you save in your IDE
hg qrefresh to update the patch
hg commit --mq to make the small changeset in the patch queue repo
and when you are done
hg qfinish fixing-the-save-btn converts the patch into a changeset to be pushed
This keeps your fumblings local to your repo complete with what was changed every time you saved, but only pushes a changeset when it is complete. You could also qpop or qpush to change which item you were working on.
If you were to try the squash method, you'd lose the fumbling history when you squashed the changesets down. Either that or you'd be stuck trying to migrate work to/from the 'real' repository, which, I can tell you from experience, you don't want to do. :)
I would suggest you to use branches. When you start a new feature, you create a new branch. You can commit as many and often as you like within that branch. When you are done, you merge the feature branch into your trunk. In this way, you basically separate the history into two categories: one in fine-grain (history in feature branches), and the other in coarse-grain (history in the trunk). You can easily look at either one of them using the command: hg log --branch <branch-name>.

How to manage concurrent development with mercurial?

This is a best practice question, and I expect the answer to be "it depends". I just hope to learn more real world scenarios and workflows.
First of all, I'm talking about different changes for the same project, so no subrepo please.
Let's say you have your code base in an hg repository. You start to work on a complicated new feature A, then a complicated bug B is reported by your trusted tester (you have testers, right?).
It's trivial if (the fix for) B depends on A. You simlply ci A then ci B.
My question is what to do when they are independent (or at least it seems now).
I can think of the following ways:
Use a separate clone for B.
Use anonymous or named branches, or bookmarks, in the same repository.
Use MQ (with B patch on top of A).
Use branched MQ (I'll explain later).
Use multiple MQ (since 1.6)
1 and 2 are covered by an excellent blog by #Steve Losh linked from a slightly related question.
The one huge advantage of 1 over the other choices is that it doesn't require any rebuild when you switch from working on one thing to the other, because the files are physically separated and independent. So it's really the only choice if, for example, A and/or B touches a header file that defines a tri-state boolean and is included by thousands of C files (don't tell me you haven't seen such a legacy code base).
3 is probably the easiest (in terms of setup and overhead), and you can flip the order of A and B if B is a small and/or urgent fix. However it can get tricky if A and B touches the same file(s). It's easy to fix patch hunks that failed to apply if A and B changes are orthogonal within the same file(s), but conceptually it's still a bit risky.
4 can make you dizzy but it's the most powerful and flexible and scalable way. I default hg qinit with -c since I want to mark work-in-progress patches and push/pull them, but it does take a conceptual leap to realize that you can branch in MQ repo too. Here are the steps (mq = hg --mq):
hg qnew bugA; make changes for A; hg qref
mq branch branchA; hg qci
hg qpop; mq up -rtip^
hg qnew bugB; make changes for B; hg qref
mq branch branchB; hg qci
To work on A again: hg qpop; mq up branchA; hg qpush
It seems crazy to take so many steps, and whenever you need to switch work you must hg qci; hg qpop; mq up <branch>; hg qpush. But consider this: you have several named release branches in the same repository, and you need to work on several projects and bug fixes at the same time for all of them (you'd better get guaranteed bonus for this kind of work). You'd get lost very soon with the other approaches.
Now my fellow hg lovers, are there other/better alternatives?
(UPDATE) qqueue almost makes #4 obsolete. See Steve Losh's elegant description here.
I would always use named branches, because that lets Mercurial do its job: to keep your project history, and to remember why you made which changes in what order to your source code. Whether to have one clone or two sitting on your disk is generally an easy one, given my working style, at least:
Does your project lack a build process, so that you can test and run things right from the source code? Then I will be tempted to have just one clone, and hg up back and forth when I need to work on another branch.
But if you have a buildout, virtualenv, or other structure that gets built, and that might diverge between the two branches, then doing an hg up then waiting for the build process to re-run can be a big pain, especially if things like setting up a sample database are involved. In that case I would definitely use two clones, one sitting at the tip of trunk, and one sitting at the tip of the emergency feature branch.
It seems like there's no more or better choices than the ones I listed in the question. So here they are again.
Use one clone per project.
Pros: total separation, thus no rebuild when switching projects.
Cons: toolchain needs to switch between two clones.
Use anonymous or named branches, or bookmarks, in the same repository.
Pros: standard hg (or any DVCS) practice; clean and clear.
Cons: must commit before switching and rebuild after.
Use MQ with one patch (or multiple consecutive patches) per project.
Pros: simple and easy.
Cons: must qrefresh before switching and rebuild after; tricky and risky if projects are not orthogonal.
Use one MQ branch (or qqueue in 1.6+) per project.
Pros: ultra flexible and scalable (for the number of concurrent projects)
Cons: must qrefresh and qcommit before switching and rebuild after; feels complicated.
Like always, there's no silver bullet, so pick and choose the one right for the job.
(UPDATE) For anyone who's in love with MQ, using MQ on top of regular branches (#2 + #3) is probably the most common and preferable practice.
If you have two concurrent projects with baseline on two branches (for example next release and current release), it's trivial to hop between them like this:
hg qnew; {coding}; hg qrefresh; {repeat}
hg qfinish -a
hg update -r <branch/bookmark/rev>
hg qimport -r <rev>; {repeat}
For the last step, qimport should add a -a option to import a line of changesets at once. I hope Meister Geisler notices this :)
So the question is, at the point when you are told to stop working on feature A, and begin independent feature B, what alternative options are there, for: How to manage concurrent development with mercurial?
Let's look at the problem with concurrency removed, the same way you write threaded code- define a simple work flow for solving any problem given to you, and apply it to each problem. Mercurial will join the work, once it's done. So, programmer A will work on feature A. Programmer B will work on feature B. Both just happen to be you. (If only we had multi-core brains:)
I would always use named branches, because that lets Mercurial do its job: to keep your project history, and to remember why you made which changes in what order to your source code.
I agree with Brandon's sentiment, but I wonder if he overlooked that feature A has not been tested? In the worst case, the code compiles and passes unit tests, but some methods implement the previous requirements, and some methods implement the new ones. A diff against the previous check-in is the tool I would use to help me get back on track with feature A.
Is your code for feature A at a point when you would normally check it in? Switching from feature A to working on feature B is not a reason to commit code to the head or to a branch. Only check in code that compiles and passes your tests. My reason is, if programmer C needs to begin feature C, a fresh checkout of this branch is no longer the best place to start. Keeping your branch heads healthy, means you can respond quickly, with more reliable bug fixes.
The goal is to have your (tested and verified) code running, so you want all your code to end up merged into the head (of your development and legacy branches). My point seems to be, I've seen branching used inefficiently: code becomes stale and then not used, the merge becomes harder than the original problem.
Only your option 1 makes sense to me. In general:
You should think your code works, before someone else sees it.
Favor the head over a branch.
Branch and check-in if someone else is picking up the problem.
Branch if your automated system or testers need your code only.
Branch if you are part of a team, working on a problem. Consider it the head, see 1-4.
With the exception of config files, the build processes should be a checkout and a single build command. It should not be any more difficult to switch between clones, than for a new programmer to join the project. (I'll admit my project needs some work here.)

What's the feature in Mercurial that gives me "checkpoints" that I can diff against without commiting frequent, breaking, small changes?

I'm developing a project, and I am making small, exploratory changes. After each change, I'd like to diff against the previous version I had. However, I don't want to commit each of these small changes to the permanent history until I'm satisfied that the final change should be made permanent. Then I'd like to commit it in one go.
What's the feature in Mercurial that lets me do this?
I think you're looking for mercurial queues... it allows you to maintain a set of patches against source without committing them. You can push and pop patches until you get things right, then commit as appropriate.
Nice blog post here http://www.canonware.com/~ttt/2008/04/using-mercurial-patch-queues-for-daily.html
Or official documentation here http://hgbook.red-bean.com/read/advanced-uses-of-mercurial-queues.html
You can use MQ as Sam mentioned, or you could just commit as usual and then use the Collapse extension or the HistEdit extension to fold the "intermediate" changesets together. You would just need to make sure you don't push them anywhere in the mean time.

best practices in mercurial: branch vs. clone, and partial merges?

...so I've gotten used to the simple stuff with Mercurial (add, commit, diff) and found out about the .hgignore file (yay!) and have gotten the hang of creating and switching between branches (branch, update -C).
I have two major questions though:
If I'm in branch "Branch1" and I want to pull in some but not all of the changes from branch "Branch2", how would I do that? Particularly if all the changes are in one subdirectory. (I guess I could just clone the whole repository, then use a directory-merge tool like Beyond Compare to pick&choose my edits. Seems like there ought to be a way to just isolate the changes in one file or one directory, though.)
Switching between branches with update -C seems so easy, I'm wondering why I would bother using clone. I can only think of a few reasons (see below) -- are there some other reasons I'm missing?
a. if I need to act on two versions/branches at once (e.g. do a performance-metric diff)
b. for a backup (clone the repository to a network drive in a physically different location)
c. to do the pick&choose merge like I've mentioned above.
I use clone for:
Short-lived local branches
Cloning to different development machines and servers
The former use is pretty rare for me - mainly when I'm trying an idea I might want to totally abandon. If I want to merge, I'll want to merge ALL the changes. This sort of branching is mainly for tracking different developers' branches so they don't disturb each other. Just to clarify this last point:
I keep working on my changes and pull my fellow devs changes and they pull mine.
When it's convenient for me I'll merge ALL of the changes from one (or all) of these branches into mine.
For feature branches, or longer lived branches, I use named branches which are more comfortably shared between repositories without merging. It also "feels" better when you want to selectively merge.
Basically I look at it this way:
Named branches are for developing different branches or versions of the app
Clones are for managing different contributions to the same version of the app.
That's my take, though really it's a matter of policy.
For question 1, you need to be a little clearer about what you mean by "changes". Which of these do you mean:
"I want to pull some, but not all, of the changesets in a different branch into this one."
"I want to pull the latest version of some, but not all, of the files in a different branch into this one."
If you mean item 1, you should look into the Transplant extension, specifically the idea of cherrypicking a couple of changesets.
If you mean item 2, you would do the following:
Update to the branch you want to pull the changes into.
Use hg revert -r <branch you want to merge> --include <files to update> to change the contents of those files to the way they are on the other branch.
Use hg commit to commit those changes to the branch as a new changeset.
As for question 2, I never use repository clones for branching myself, so I don't know. I use named branches or anonymous branches (sometimes with bookmarks).
I have another option for you to look into: mercurial queues.
The idea is, to have a stack of patches (no commits, "real" patches) ontop of your current working directory. Then, you can add or remove the applied patches, add one, remove it, add another other one, etc. One single patch or a subset of them ends up to be a new "feature" as you probably want to do with branches. After that, you can apply the patch as usual (since it is a change). Branches are probably more useful if you work with somebody else... ?