This answer shows how you can demote a commit to a patch, but how can I convert an mq patch to local changes only?
Short answer
Make sure the patch is applied, then:
hg qrefresh nothing
hg qpop --keep-changes
hg qdelete "Name of patch"
Long answer
First, you need to make sure no changes are tracked by the patch. To do that, use
hg qrefresh nothing
nothing is just a random file name that is not in the repository. I usually use hg qref 0 for brevity. hg qrefresh accepts an optional file pattern. If it is given, the patch will track the changes that match the pattern - and only those. When nothing matches the file pattern, no changes will be tracked by the patch, and thus there will be local changes only.
Now you have a useless patch lying around, and you have some local changes. To clean up, you can do
hg qpop --keep-changes
to pop the patch even though there are local changes. Finally, to remove the dead, empty and unapplied patch you can use
hg qrm "Name of patch"
You can't remove an applied patch, which is why you need the hg qpop --keep-changes step.
(Note: hg qrm and hg qremove are aliases of hg qdelete.)
If using TortoiseHg
With TortoiseHg, exporting the patch to the clipboard (Workbench > right-click the patch > Export > Copy Patch), then unapplying the patch, and finally importing from the clipboard with the destination being "Working Directory" seems to work. Here are some screen captures demonstrating this procedure:
An arguably simpler alternative:
hg qfinish qtip
hg strip -k tip
That is, finish the patch and then remove the resulting commit while retaining its changes (the -k option to strip).
Related
I have an applied patch in my Mercurial queue, how do I convert this patch into uncommited changes in my working copy (as though I'd never created the patch using qnew)?
Tell Mercurial to refresh the patch but exclude all files. This will leave all changes in the patch uncommitted in your working folder. You are left with an empty applied patch that can be popped off and deleted.
hg qref -X *
hg qpop -f
hg qdel <patch>
Well, in the absence of other answers, here's what I ended up doing:
First pop the patch off the patch stack so it is no longer applied
hg qpop thepatchname --keep-changes
I'm not sure if the --keep-changes was necessary, but I had local uncommitted changes I wanted to keep.
Next I had to shelve some uncommitted changes in my working copy so I could apply a patch
hg shelve
Now apply the patch, stored in .hg/patches using the import command, with the --no-commit option so the patch is not commited to your repository.
hg import .hg/patches/thepatchname --no-commit
You can now delete the patch if you like.
I have a commit onto which I have amended some files. Some of these files that were part of the amend I do not want in this commit. Is there a way in Mercurial to remove certain files from the commit without losing the changes I have made to them? Thank you.
Steps:
Made some changes
hg commit -m
Made some more changes (some of these file accidentally amended)
hg amend
Try out:
hg forget somefile.txt
hg commit --amend
If the file was new (i.e. you had used hg add).
If that file already existed try:
cp somefile.txt somefile.txt.bak
hg revert somefile.txt --rev .~1
hg commit --amend
Which is basically telling mercurial to revert the file (somefile.txt) back to the state it was one revision ago (--rev .~1).
Just make sure to back up the file you are reverting before entering the command so that you do not lose your changes. I was under the impression mercurial does this automatically for you, but after testing it quickly I'm not so sure.
hg uncommit somefile.txt does exactly this for me.
Like plain git reset, it removes the change from the commit but leaves the file contents unchanged, so now hg diff shows the change you just uncommitted.
The uncommit command claims to come from the uncommit extension, but may actually be coming from the evolve extension, I admit I'm not 100% sure!
I issued hg qnew without realizing that it includes any outstanding changes into the patch. I'd like to back that out and pick only specific changes using hg qrecord. How can I undo qnew?
Your answer definitely works — with newer Mercurial's you can use hg strip --keep to avoid doing the import step:
$ hg strip --keep .
$ hg qdelete patch-name
The --keep flag makes strip ignore the working copy while working, that is, it deletes the commit (like hg qpop would do) but it doesn't undo the changes to the files. After stripping you still have the patch in your series (unapplied) and you can then delete it.
I've found an anwer here:
hg qpop
hg import --no-commit .hg/patches/patch-name
hg qdelete patch-name
Please add a better way, if you know.
Update: Based on Aldo's answer, there is another way:
hg qnew test
# We can undo the above qnew as:
hg qrefresh -X '*'
hg qpop -f
hg qdelete test
If you just want to undo the latest qnew retaining all your local changes, one option is:
qcrefresh 123
hg qpop -f
hg qdelete <name of the patch>
Notice that 123 is just a random string: you are telling mercurial to only include the (hopefully nonexistsnt) 123 file in the current patch.
Newer versions of Mercurial When you issue will issue a warning about the fact 123 file does not exist, but this is exactly what we want here.
If you want to retain some of the changes in the current path, you can use the qcrefresh command from the crecord extension, which allows to graphically select the changes to be included in the current patch. You need to download it from Bitbucket, extract the archive and configure it in .hgrc:
[extensions]
crecord = <path/to/crecord/package>
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.
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.
Execute hg qpop -a to remove all patches from the stack
Execute hg qpush --move some-patch to apply "some-patch" without applying whatever other patches may be before it in the patch stack
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
If you do an hg pull and then an hg update (or an hg merge), is there a way to back this out? Ie: revert your repository to the state prior to doing the hg pull?
I believe you can do hg update -r n where you would specify the changeset prior to the pull as n. Though I'm guessing this will still leave the changesets in your repository but this isn't really what we want. ??
hg strip will remove revisions from a repository. Like all powerful commands, its dangerous, so be careful.
https://www.mercurial-scm.org/wiki/StripExtension
Also see:
https://www.mercurial-scm.org/wiki/EditingHistory
If you catch your mistake immediately (or reasonably soon), you can just use hg strip REV to roll back the latest (one or more) changes. ...
Ok, you can't rollback because you've done a commit. What you can do is use 'hg strip' which is part of mq (after 2.8 strip is in it's own extension), or use mq to remove the changes. Either way I suggest you do everything on another clone, just in case.
To do strip, update to a revision that you want to keep, and then
hg strip <REV>
where <REV> is the first revision you want to remove. It will remove that one and all decendents (including your merge commit).
Alternatively you can
hg qnew (if you don't already have a patch queue)
hg qimport <REV>
which will import a single revision into the patch queue. You can then add more, and then use the mq commands to edit, rearrange, delete, or whatever you want to do with those revisions. qdel deletes the current patch.
Edit: Obviously, you'll need to enable the MQ extension for both of these, unless you're using 2.8 or later. In that case strip is in the strip extension, and mq in the mq extension. Both are shipped with the standard installation.
hg --rollback can be used to undo the last transaction so as long as your hg pull is still the most recent transaction then you can use that. This command should be used with care though. See here for some more details.
you can:
hg update -C <version>
see the mercurial FAQ.
If you want to remove all traces of the pull form your history then you need to use an extension as Bert F suggests (the philosophy in mercurial is to never change history)
if you dont mind history containing your mistake you have two slightly different options hg update -C -r which will create a new branch at the version you specify or hg revert -r which will stay on the same branch but create a new uncommited change undoing everything.