hg strip vs hg backout and hg revert - mercurial

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

Related

Undoing a revert in mercurial (not a duplicate query)

I have a mercurial repo with no uncommitted changes. I was on revision 846, and decided my last 2 commits were junk and wanted to carry on as if from revision 844. So I was going to type:
hg revert -r 844 --all
Unfortunately I mistyped, and wrote:
hg revert -r 44 --all
So my whole repository has changed dramatically, including directory structure. I don't see any .orig files, so I don't think the answer in:
How to undo a revert in mercurial
helps me.
hg log still has all of my commits up to revision 846 - do you think I can revert back to revision 846?
Advice very welcome
hg revert just sets your working copy to the revision that you specify so if you didn't do a commit after the revert then your repository has not changed. To fix it you can just do hg update -C and then delete all the .orig files.
After that you can do the correct revert statement to remove the last two revisions.
If you did do the commit then the command that you wanted to do (hg revert -r 844 --all) would still get you to the point that you want by undoing the revert commit as well as the two commits that you originally intended to undo.

Mercurial pushing update to previous revision

I ran hg update -r REVISION to revert a branch to a previous revision, but when I try to push this to a remote repository it says "no changes found". How can I accomplish this?
To revert the files to a previous revision you can use
hg revert -r REVISION
This will change your working directory files to what they were at that revison. Then you
will need to commit these changes before pushing.
hg update -r REVISION changes the working directory's parent to be that revision as well as changes the contents of the working directory to that revision. This is not what you want here.
hg update only affects the state of your working directory, not the repository itself. If you want to "undo" the effects of one or more previous revisions, you will need to change the repository by committing a new changeset that reflects those changes. You could do it manually but hg's builtin backout command makes this easy to do. See a brief description here. There is a detailed explanation of backout here.

Mercurial (hg) equivalent of git reset (--mixed or --soft)

what would be an equivalent mercurial command (or workflow) for
git reset --mixed HEAD^
or
git reset --soft HEAD^
i.e. I want leave the working tree intact but get the repository back into the state it was before the last commit. Surprisingly I did not find anything useful on stackoverflow or with google.
Note that I cannot use
hg rollback
as I've done some history rewriting using HistEdit after the last commit.
Added to clarify:
After some rebasing and history editing I had ended up with A<--B<--C. Then I used HistEdit to squash B and C together, obtaining A<--C'. Now I want to split up the commit C' (I committed the wrong files in B). I figured the easiest way to do this was to get the repository back to state A (which technically never existed in the repository because of all the rebasing and history editing before hand) and the working tree to the state of C' and then doing two commits.
The right way to replicate git reset --soft HEAD^ (undo the current commit but keep changes in the working copy) is:
hg strip --keep -r .
-1 will only work if the commit you want to strip is the very last commit that entered the repository. . refers to the currently checked out commit, which is the closest equivalent Mercurial has to Git's HEAD.
Note that if . has descendants, those will get stripped away too. If you'd like to keep the commit around, then once you have the commit ID, you can instead:
hg update .^
hg revert --all -r <commit id>
This will update to the commit's parent and then replace the files in the working copy with the versions at that commit.
I believe the more modern and simpler way to do this now is hg uncommit. Note this leaves behind an empty commit which can be useful if you want to reuse the commit message later. If you don't, use hg uncommit --no-keep to not leave the empty commit.
hg uncommit [OPTION]... [FILE]...
uncommit part or all of a local changeset
This command undoes the effect of a local commit, returning the affected
files to their uncommitted state. This means that files modified or
deleted in the changeset will be left unchanged, and so will remain
modified in the working directory.
If no files are specified, the commit will be left empty, unless --no-keep

Backout unwanted changes and make a patch out of them

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.

Rollback multiple commits (before Pushed to public) in Mercurial

I am aware that rollbacks can remove commits from the latest changeset in a local repository. However, is it possible to remove all the latest commits since the previous push without having to re-clone the share repository?
You can use the hg strip command, part of the mq extension:
hg strip REV
This will remove that revision + all its descendants.
Before you try this, make a copy/clone of the repository to experiment in.
You could make a new repo with hg clone:
hg clone -r last_good_changeset localrepo newlocalrepo
If you are using mercurial eclipse, you can rollback once, then shelve those changes, then export the multiple sequential commits as patches, strip those commits, then import those patches in the same order, so in case you had conflicting patches, they overwrite each other in the desired way.
Finally you can unshelve your first rollback. This achieves the same effect as if you were rolling back more than once.