I'am collaborating with someone on remote repo. We realized that changes I made should be removed out of repo. But those changes are in many changesets and mixed with someone's changes.
We decided to remove my changes just before I commit another changeset. So I've made a patch out of uncommited changes and qpop it.
Now I want to backout rest of my changes out of remote and selectively make patch out of those changes leaving my colleague changes untouched.
Moreover I want to have diffs from new patch with diffs from patch_ive_made_before in one patch. So in other words - I'd like to have one patch out of 2 different changesets. Do I have to do it manually?
Then after I do it, I will commit/push cleared changes into the repository.
How this could be done with Mercurial Queues?
You can make a patch that is the reverse of a previous change using this command:
hg diff --change NODEID_YOU_REGRET --reverse > undoes-what-you-regret.patch
That patch could be put in a mercurial queue using:
hg qimport undoes-what-you-regret.patch
Were I doing it, though, I'd skip mq entirely and just do:
hg backout --rev NODEID_YOU_REGRET
that will create a new head, which you can hg merge into any line of development that's a decendent of the original change -- i.e.: anything that has that code.
Related
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.
What is the difference between the mercurial commands,
hg strip
hg backout
hg revert
All these commands basically are used to revert/undo the effects of an earlier changeset.
hg strip removes the changeset and all its descendants from the repository. It will be as if the changes never existed. Be careful when using this on public changesets as it will not remove it from any other repository and you'll get them back next time you pull.
hg backout creates a new changeset to reverse the effect of an earlier changeset. The old changeset will still remain in the repository but so will a new changeset to remove the changes.
hg revert with a revision updates the working copy to the specified revision. If you then commit that working copy it will have the effect of reverting all changes since.
Other answers with more info on revert and backout:
What is the difference between hg revert and hg backout?.
Mercurial — revert back to old version and continue from there.
At certain moment of time I had to build Jenkins pipeline where POM files should be reverted each time the job starts. And the problem which I have faced is: how to revert all POM files reversively.
Since this answer is one of the first on google, I want to contribute my solution for people with same problem
hg revert */pom.xml
I have 5 outgoing changesets available to push from my local Mercurial repo, and I only want to push one of these at this time. This one changeset lies in the middle of all available.
For example I have the following revisions:
6639
6546
6545
6544
6543
and I only want to push 6545. Any easy way to do this?
You can only push the consecutive list of changesets up to the required.
So
hg push -r 6545
will push 6543..6545.
And you cannot push just 6545 because without preceding changesets its changes make no sense.
You could use the Mercurial Queues extension to do this. You may need to enable the mq extension which is detailed on the linked page.
You would import all the revisions into the queue, pop them all off the stack and then apply the one that you want before pushing and then applying the rest. Something like this:
> hg qimport --rev 6639
> hg qimport --rev 6543:6546
> hg qpop --all
> hg qpush --move 6545.diff
Here you might have to resolve conflicts
> hg qfinish --applied
> hg push
> hg qpush --all
Again, might need to resolve conflicts here.
This has left your repository with revision 6545 applied and pushed (but with a different revision number now) and the rest of your changes applied and not pushed.
What you want is not possible. A revision must put a repository in a definite state, but if you could push 6545 and the remote repository updated to it, it would not include the changes from earlier (not pushed) revsets. This goes against the core design of mercurial. What you can do is:
a) distribute a diff (patch) that contains the same changes as rev 6545. You can do this via hg diff or in other ways, but applying the patch is not inherently connected to your rev 6545: it is a separate revision that "happens" to make the same changes. If you're lucky, they can be merged in the future without problems. Or
b) rewrite your history, temporarily (with the mq extension) or permanently (with the help rebase or other extensions) so that 6545 is placed immediately after the already-commited revisions. You can then push it like any other revision whose ancestors have already been pushed.
I want to completely delete a Mercurial commit as if it was never entered in the repository and move back to my prior commit.
Is this possible?
If it was your last commit and you haven't pushed it anywhere, you can do that with rollback. Otherwise, no. Not really. Time to change your passwords.
Edit: It has been pointed out that you can clone from an older revision and merge in the changes you want to keep. That's also true, unless you have pushed it to a repo you don't control. Once you push, your data is very likely to be very hard to get back.
You can try to remove mq info about your commit.
For this you need to go File->Settings->Extensions.
There check mq and restart gui.
After that just right click on unneeded commit and
ModifyHistory->Strip
To edit the history I would use the Histedit Extension extension.
hg histedit 45:c3a3a271d11c
However keep in mind this only makes sense in a situation where you have not yet pushed the commits to the public repository, you own the public repository and/or you can account for all the clones out there. If you receive the following error:
abort: can't rebase immutable changeset 43ab8134e7af
It means that Mecurial thinks this is a public changeset (see phases) that has already been pushed - you can force it to be a draft again doing:
hg phase -f -d 45:c3a3a271d11c
I encounter this fairly often. I make a commit and then pull to push. But then there is something incoming that makes my newly made commit unnecessary. A plain hg rollback isn't enough because it only undoes the pull...
This is the thing to do:
hg strip <rev>
Things are painless when you don't push your changesets anywhere.
If it's more than one commit and/or you already pushed it somewhere else, you can clone your repository and specify the last changeset that should be cloned.
See my answer here how to do this:
Mercurial: Fix a borked history
If you only committed locally and didn't push, you can just create a clone locally (as described in my link) and you're done.
If you already pushed to some remote repository, you would have to replace that with your clone.
Of course it depends if you are able (or allowed) to do this.
You can use "hg backout" to do a reverse merge basically. All options are discussed in the freely available book "Mercurial: The Definitive Guide":
http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html
If using tortoise you can use modify history > strip...
Yes. Unless I am mistaken, as of v2.3 (rel. 2012/08/01) you can use the HisteditExtension with a drop command to drop a commit, along with strip or backout to remove changes.
A simple Google search on the feature: https://www.google.com/webhp#q=histedit+drop
In 2022 I do use evolve extension. It is one of the best extensions for this purpose.
To prune unwanted changeset, if you for example did a quick hack to get the code working:
$ echo 'debug hack' >> file1.c
$ hg commit -m 'debug hack'
Now you have a proper patch you can do hg prune .:
$ hg prune .
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
working directory is now at 2a39221aaebb
1 changesets pruned
If you push the change to the remote repository you will find only obsolescence markers:
$ hg push
searching for changes
no changes found
remote: 1 new obsolescence markers
To check the changes to your local repo you can pull from the remote one:
$ hg pull
pulling from ssh://userid#server/repo
searching for changes
no changes found
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.