Splitting single change set in 2 different commits [duplicate] - mercurial

I want to commit only some of the modifications I made to my files and my preferred way to do this is to shelve/stash away the changes I don't want to commit. This allows me to test the changes I will commit before actually commiting them.
The problem I am having is that when I use the "shelve" tool in tortoisehg I can't find any way to split a chunk into two smaller chunks. For example, I have a chunk that looks like this:
## -1,1 +1,2 ##
-hallo world
+hello world
+something else
I would like to shelve away the "something else" so I can commit just the "hallo->hello" fix. However, since tortoisehg is seeing this a single chunk I can either shelve both or none of the changes.
I also tried using the shelve extension via the command line but from what I understood from the documentation it does not offer the feature to shelve away only parts of the files.

You can accomplish your goal from the command line. There are interactive versions of hg commit, hg revert, and hg shelve, and they have low-level options to hack a patch together if needed; you can use them with the -i (or --interactive) command line option.
This means that you can build up a commit with hg commit -i and hg commit --amend -i. If you have the evolve extension installed, you can use hg uncommit to pull changes out of the commit again; if not, you can use hg revert -r .~1 or hg revert -i -r .~1 a file and use hg commit --amend -i again to fix it up.
In order to select individual lines from a patch, you have two options. You can use e to edit the patch (but see below for a more convenient option).
You can then use hg shelve to shelve the remaining changes.
You can in principle also do this with hg shelve -i, however, there's a big caveat; if you edit patches for hg shelve -i, then Mercurial's merge mechanism will get confused and not process the change cleanly, but dump you in a merge tool in order to resolve this apparent conflict (which means lots of extra work to resolve it). Hence why I strongly recommend using hg commit -i and hg commit --amend -i if you want to manipulate things at the line level (hg shelve -i works fine if you don't edit the patches).
For added convenience (that prevents you from editing patches), you can also enable the experimental crecord option by adding the following to your hgrc file:
[experimental]
crecord = true
This will enable a terminal-based hunk editor for hg commit -i, hg revert -i, and hg shelve -i that allows you to select individual lines and hunks (internally, that works roughly the same way as editing patches). Use the ? key to get help in that editor; use f to unfold/fold individual hunks and the space key to select hunks/lines.
Note that line-based selection for this tool in conjunction with hg shelve -i comes with the same caveats as editing patches; i.e. use hg commit -i and hg commit --amend -i instead if you want to do line-based selection. Also, line-based selection for hg revert -i will still revert the entire hunk. (There's a reason why this option is still marked as experimental.)

I don't know a command to do this, but if you are using tortoiseHg, you can do that by selecting modified sections (checkboxes) in the commit preview area.
See Mercurial cherry picking changes for commit

Related

Remember uncommitted changes

I have some uncommitted changes C in my repo. I would like remember that changes in any way and get clean code (without that changes), make a little change and commit it. Now, I would like to recover my changes C and continue working on it. I know that I can deal with it using a lot of ways, but that ways are irritating. How to do it using mercurial?
So, to be more precise I need something like a stack:
Working on the code. Remember changes C on the stack.
hg update --clean
Make a change C2. Commit it.
Pop from stack a changeset C and work on it. But, now the repositorium contains committed change C2 and uncommitted C. It may cause that I need to merge but I expect that this merge will be invisible from the point of view repositorium.
While you certainly can work with mercurial queues, there's IMHO an easier and nicer way: change your default phase to secret and work with those commits like normal commits. Commits in phase secret are mutable and will not be exposed by push and pull commands acting on the repo.
This process has the advantage that you do not need to change your workflow - whether you work with commits you want to share (phase draft or public), or whether you still consider them work-in-progress and keep them locally only.
Additionally if you enable the evolve extension, you gain several benefits: it becomes even easier to amend commits and evolve (thus rebase) all child commits which depend on it.
The big advantage over the use of the mercurial queues is that you can make full use of the inbuild merge features - thus if the underlaying code changes, rebasing the new changesets is WAY easier and natural than using queues and hg shelve.
See the introduction to hg phases and changeset evolution which needs the evolve extension.
Enable the Mercurial Queues extension in your mercurial.ini or .hgrc file:
[extensions]
mq =
Then you can,
hg qnew save # save work in progress as a temporary commit
hg qpop # remove that commit
Make some more changes....
hg ci -m "new changes"
hg qpush # push the saved commit back.
hg qfinish -a # convert all temp commits to full commits.
You can also enable the shelve extension:
[extensions]
shelve =
Then you can:
hg shelve # "put away" current uncommitted changes.
*do other work*
hg unshelve # bring the shelved changes back
See hg help mq and hg help shelve for more info.
I've tried shelve, mq as described in other answers but to be honest I generally stick with:
hg diff > saved.patch # This assumes you've not aliased diff to a UI!!!
hg update -C
.. work
hg patch -f --no-commit saved.patch # I alias this for less typing
.. continue
Less book-keeping involved, its never gone wrong unlike shelve, and the patch itself is more easily portable. Just use common-sense and either make sure the patch applies fully, or use the --partial option and manually complete the patch.

Is there an hg equivalent of `git stash save -p` that can split chunks into smaller chunks?

I want to commit only some of the modifications I made to my files and my preferred way to do this is to shelve/stash away the changes I don't want to commit. This allows me to test the changes I will commit before actually commiting them.
The problem I am having is that when I use the "shelve" tool in tortoisehg I can't find any way to split a chunk into two smaller chunks. For example, I have a chunk that looks like this:
## -1,1 +1,2 ##
-hallo world
+hello world
+something else
I would like to shelve away the "something else" so I can commit just the "hallo->hello" fix. However, since tortoisehg is seeing this a single chunk I can either shelve both or none of the changes.
I also tried using the shelve extension via the command line but from what I understood from the documentation it does not offer the feature to shelve away only parts of the files.
You can accomplish your goal from the command line. There are interactive versions of hg commit, hg revert, and hg shelve, and they have low-level options to hack a patch together if needed; you can use them with the -i (or --interactive) command line option.
This means that you can build up a commit with hg commit -i and hg commit --amend -i. If you have the evolve extension installed, you can use hg uncommit to pull changes out of the commit again; if not, you can use hg revert -r .~1 or hg revert -i -r .~1 a file and use hg commit --amend -i again to fix it up.
In order to select individual lines from a patch, you have two options. You can use e to edit the patch (but see below for a more convenient option).
You can then use hg shelve to shelve the remaining changes.
You can in principle also do this with hg shelve -i, however, there's a big caveat; if you edit patches for hg shelve -i, then Mercurial's merge mechanism will get confused and not process the change cleanly, but dump you in a merge tool in order to resolve this apparent conflict (which means lots of extra work to resolve it). Hence why I strongly recommend using hg commit -i and hg commit --amend -i if you want to manipulate things at the line level (hg shelve -i works fine if you don't edit the patches).
For added convenience (that prevents you from editing patches), you can also enable the experimental crecord option by adding the following to your hgrc file:
[experimental]
crecord = true
This will enable a terminal-based hunk editor for hg commit -i, hg revert -i, and hg shelve -i that allows you to select individual lines and hunks (internally, that works roughly the same way as editing patches). Use the ? key to get help in that editor; use f to unfold/fold individual hunks and the space key to select hunks/lines.
Note that line-based selection for this tool in conjunction with hg shelve -i comes with the same caveats as editing patches; i.e. use hg commit -i and hg commit --amend -i instead if you want to do line-based selection. Also, line-based selection for hg revert -i will still revert the entire hunk. (There's a reason why this option is still marked as experimental.)
I don't know a command to do this, but if you are using tortoiseHg, you can do that by selecting modified sections (checkboxes) in the commit preview area.
See Mercurial cherry picking changes for commit

Mercurial - Working with Queues similar to Shelves?

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

How to revert a Mercurial hg pull?

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.

Can I revert a range of lines in a file with mercurial?

I often notice a few unwanted changes when I review my working copy (with hg status and hg diff) right before a commit. For example, I might have temporarily added or remove some code just for the duration of a debugging session.
I know I can use hg revert to remove unwanted changes, but this removes all the changes in the entire file. Is there a way to revert just a part of a file?
I'm not sure if you can revert individual lines explicitly, but what I do in situation like yours is to commit the good code and revert the rest (the bad code). This workflow is easy using Mercurial's record or crecord extension (I recommend the latter one).
I've been doing this with the interactive ncurses style ui hg revert -i that lets you walk around and select the parts you want to destroy, either file, diff chunk or line by line, as you please, depending on how deep you unfold your changes.
I am not sure if this is a standard hg feature or not, you can verify easily enough if yours has it:
> hg revert --help --verbose | grep -- -interactive
-i --interactive interactively select the changes (EXPERIMENTAL)
Just remember that the changes you mark (X) will be what gets nuked, not what you retain.
Assuming you have the record and shelve extensions enabled, you can do as follows:
hg record -m "garbage" # pick out and commit the change you want to revert
hg shelve --all # temporarily hide other changes
hg strip tip # remove the garbage changeset
hg unshelve # restore the changes you want to keep
One way is using a graphical diff tool like kdiff3. If you feed it the diff and choose "merge current file" you can go line by line and pick what you want.
The better way is to commit more often. If you make a habit to commit right before adding debugging code, then either commit or revert your debug code before adding your "real" code, it makes it very easy to remove your debug code because it has its own revision. Alternately, you can put your debugging code in a separate branch altogether.
The TortoiseHg GUI's "Commit" window has a "Hunk Selection" tab that allows selection of specific sections of a file's changes to be committed.
I've got a different answer for your problem, which is the same problem I have. This is a great use case for mercurial queues!
When I am about to start adding debugging code to a change that I think is ready, I do the following:
hg qnew -m "fix for bug #123" fix.patch # basically a local-only commit
hg qnew -m "debugging" dbg.patch # prepare the next changeset at the tip
[add my debugging]
hg qrefresh # update the changeset at the tip
[...]
hg qpop # pop the debugging off the repo history
It takes a little bit of getting used to -- you end up having to reorder your patches to then fold whatever fixes you made into the original work patch.
Also, check out Bill Barry's attic extension. This page talks about how to use it for a few different workflows and how that compares to using mq. https://www.mercurial-scm.org/wiki/AtticExtension
If the commit where you want the change is e.g. ba1c841aaff4,
the easiest is to use:
hg meld -r ba1c841aaff4^ <filename>
Now click on a right arrow (pointing to the right) in the middle to revert your lines, save the file and close meld. kdiff3 (old and unintuitive) can be an alternative.
Side note: in order to use meld you need to configure it in our ~/.hgrc file:
[extdiff]
cmd.meld =
[merge-tools]
meld.args=$base $local $other
Download and install meld https://meldmerge.org/
(You should have Mercurial installed locally or TortoiseHg)
Launch Meld and select Version Control View and then select you will be asked to choose a parent directory of the file you want to modify.
Select the file which has the uncommitted changes
Choose which lines you want to revert to the last commit by selecting the arrow. The document on the left is from the last commit and the right document is the file with the uncommitted changes.