How to rollback last n commits in mercurial - mercurial

I have got a requirement where I need to rollback last 10 commits. How can I do it. Please help.

The easiest thing would be to clone the repo until the last commit you want to keep.
hg clone -r last_commit_to_keep myrepo mynewrepo

If you haven't yet pushed, then you can use the Strip extension.
If you have pushed then It would be better to backout the commits.
Backing out a commit makes an additional commit of the exact opposite of the commit being removed, which gets appended to the repo. Hence you can still see the original commits in the repo history.

Related

mercurial - have I lost a commit after checking out parent and commiting there?

I committed some changes in hg, then checked out the parent of that commit and made other changes followed by another commit (from that parent).
What happened to the 1st commit? How can I find and recover it? I don't see it in the log.
What happened to the 1st commit?
It should still be there. Making the extra commit should have just created another head within the branch.
How can I find and recover it?
It should also be obvious (for finding), in Mercurial, which makes me wonder:
I don't see it in the log.
How exactly are you looking at the commit log? If you just run hg log or hg log -b <branch>, you should see all commits, or all commits in the given branch, in reverse numerical order. If you use hg log --follow, commits not reachable from the current commit will seem to disappear, because, as the documentation says:
--follow without a filename will only show ancestors or descendants of the starting revision.
In any case, you can do revision surgery if you really want to, but the simplest thing is just to merge the heads. Use hg heads . to view the heads in the current branch; check out one, and merge another, to combine the two commits with a new merge commit, making both previous heads become ordinary non-head commits, with the new merge being a single head in that branch.

Merging/Removing a commit

I have a commit i pushed earlier today that i learned i had messed up on by not adding the correct files before pushing. I fixed the revision and re-pushed it, so now i have a revision containing literally nothing new and my real revision. This could really confuse my other team members working, so i would like to either merge both together or remove my 'blank' revision.
Here is a picture of my problem:
http://img525.imageshack.us/img525/3929/revisionproblem.png
Note that i cannot undo/rollback, it tells me the transaction is not available.
If you've pushed it there's very little you can do. You could hg strip it from your local repo, but you'll get it back the next time you pull. You could edit history with hg histedit or merge two changesets with hg collapse, but none of that will get rid of the changeset you've pushed.
That said, the comment in your screenshot, "I just rolled back my latest push...", has me thinking you might have hg push and hg commit confused. They're entirely different and hg push can't be rolled back (locally). A hg push sends your local changesets out to the world -- no takebacks. A hg commit creates a new local changeset.
If you've misstated your problem and you've merely hg commited a changeset you regret you have all the extension-based options I listed above available to you. If you've really pushed it -- welcome to DVCS usage: once it's out there it's out there, and the best you can do it correct it in a subsequent commit.

Mercurial undo three hg push

I'm using mercurial VCS, I've mistakenly pushed three commits and I want them to be undone, can this be achieved?
I'm pretty sure no changes were propagated to anyone from the repository I pushed to, so I'm confident that this won't break anyones code...
I've tried hg rollback but since I have pushed I cannot undo anything in the right way. Also I know about hg backout, but I'm not sure if I should use this one for what I need...
Thanks!
EDIT
This is the graph log, I forgot to mention that some commits were part of a merge, but they too need to be undone...
tip
|
a
| \
| b
| /
c
|
d
I need to return the tip to c, or d if there is no other way to prevent that because of the merge...
If it's already pushed, there are only two things that you can do now:
1) If you are able to delete the central repository and replace it by another one:
You can clone the central repository, but tell Mercurial to clone only up to changeset "c".
Then you can take this repository (which doesn't have the wrong changes) and replace the "old" central repository (the one which does have the wrong changes) with it.
Disadvantage: if someone already pulled the unwanted commits and later pushes again, they are in the repository again.
So you need to make sure that either no one pulled the mistakes, or everybody who did deletes his clone.
2) If option 1 is not possible, you can use hg backout to undo the effects of the wrong changes - not the changesets themselves.
Quote from the link:
Backout works by applying a changeset that's the opposite of the changeset to be backed out. That new changeset is committed to the repository, and eventually merged.
So the three wrong changesets will remain in the repository, plus another three will be added, each of them reverting the effects of one of the three wrong changesets.
If you do it like this, it doesn't matter if someone else already pulled the wrong changes...as soon as he pulls the three "backout" changesets as well, everything is okay again.
If you're positive the push is the last thing that happened to that remote repository, meaning neither you nor anyone else has pushed to it, you can login to that system and run hg rollback.
If it's a repository on a machine to which you can ssh you can run this command on your local system:
ssh you#there hg -R /path/to/the/repo rollback
As always please do be really careful with rollback. It undoes the last action on the repository without altering the working directory at all, and it's not always clear what the last action was. For example, this is datalosss:
...hack...
hg commit -m 'important work'
hg update somewhere else
hg rollback
Yikes!

Mercurial undo last commit

How can I undo my last accidentally commited (not pushed) change in Mercurial?
If possible, a way to do so with TortoiseHg would be prefered.
Update
In my concrete case I commited a changeset (not pushed). Then I pulled and updated from the server. With these new updates I decided, that my last commit is obsolete and I don't want to sync it. So it seems, that hg rollback is not exactly what I'm searching for, because it would rollback the pull instead of my commit.
One way would be hg rollback (deprecated as of Hg2.7, August 2013)
Please use hg commit --amend instead of rollback to correct mistakes in the last commit.
Roll back the last transaction in a repository.
When committing or merging, Mercurial adds the changeset entry last.
Mercurial keeps a transaction log of the name of each file touched and its length prior to the transaction. On abort, it truncates each file to its prior length. This simplicity is one benefit of making revlogs append-only. The transaction journal also allows an undo operation.
See TortoiseHg Recovery section:
This thread also details the difference between hg rollback and hg strip:
(written by Martin Geisler who also contributes on SO)
'hg rollback' will remove the last transaction. Transactions are a concept often found in databases. In Mercurial we start a transaction when certain operations are run, such as commit, push, pull...
When the operation finishes succesfully, the transaction is marked as complete. If an error occurs, the transaction is "rolled back" and the repository is left in the same state as before.
You can manually trigger a rollback with 'hg rollback'. This will undo the last transactional command. If a pull command brought 10 new changesets into the repository on different branches, then 'hg rollback' will remove them all.
Please note: there is no backup when you rollback a transaction!
'hg strip' will remove a changeset and all its descendants. The
changesets are saved as a bundle, which you can apply again if you
need them back.
ForeverWintr suggests in the comments (in 2016, 5 years later)
You can 'un-commit' files by first hg forgetting them, e.g.: hg forget filea; hg commit --amend, but that seems unintuitive.
hg strip --keep is probably a better solution for modern hg.
hg strip will completely remove a revision (and any descendants) from the repository.
To use strip you'll need to install MqExtension by adding the following lines to your .hgrc (or mercurial.ini):
[extensions]
mq =
In TortoiseHg the strip command is available in the workbench. Right click on a revision and choose 'Modify history' -> 'Strip'.
Since strip changes the the repository's history you should only use it on revisions which haven't been shared with anyone yet. If you are using mercurial 2.1+ you can uses phases to track this information. If a commit is still in the draft phase it hasn't been shared with other repositories so you can safely strip it. (Thanks to Zasurus for pointing this out).
Since you can't rollback you should merge that commit into the new head you got when you pulled. If you don't want any of the work you did in it you can easily do that using this tip.
So if you've pulled and updated to their head you can do this:
hg --config ui.merge=internal:local merge
keeps all the changes in the currently checked out revision, and none of the changes in the not-checked-out revision (the one you wrote that you no longer want).
This is a great way to do it because it keeps your history accurate and complete. If 2 years from now someone finds a bug in what you pulled down you can look in your (unused but saved) implementation of the same thing and go, "oh, I did it right". :)
hg rollback is what you want.
In TortoiseHg, the hg rollback is accomplished in the commit dialog. Open the commit dialog and select "Undo".
In the current version of TortoiseHg Workbench 4.4.1 (07.2018) you can use Repository - Rollback/undo...:
Its workaround.
If you not push to server, you will clone into new folder else washout(delete all files) from your repository folder and clone new.
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
Sorry, I am not sure what the equivalent is TortoiseHg.
after you have pulled and updated your workspace do a thg and right click on the change set you want to get rid of and then click modify history -> strip, it will remove the change set and you will point to default tip.
I ran into this issue recently, although my situation was slightly different - I had already pushed the commit I wanted to undo. I solved my problem with hg backout <revision-code>. It seems to work in a similar way to git revert. From this answer:
backout: create a new commit that is the inverse of a given commit.
Net effect is an undo, but the change remains in your history.
In TortiseHg this can be done by right clicking the commit you wish to undo and selecting Backout.... TortiseHg doc here.
I think there's an argument for creating a new undo commit instead of removing the previous commit outright. From this article about git revert:
Instead of removing the commit from the project history, it figures
out how to invert the changes introduced by the commit and appends a
new commit with the resulting inverse content. This prevents Git from
losing history, which is important for the integrity of your revision
history and for reliable collaboration.

Mercurial: back out last change so codebase is clean?

I've just messed something up in Mercurial.
How do I back out the last change so that the codebase is clean - specifically so that if someone else does 'hg pull', they'll have a working codebase?
Two ways:
hg rollback as mentioned by Fred; if you've already pushed, too late. hg rollback is only suitable for local use. hg strip (also as mentioned by Fred) works the same way and is (excepting its support for backing up) equivalent to doing hg rollback a number of times, till you get back to that revision.
hg backout for when you have already pushed and just want to revert the effects of the commit (if you've accidentally pushed out sensitive data, you'll need to take more drastic measures, but if you just want it to work, use this).
If the commit is not the last-committed revision, say so and we can get into deeper stuff (or search - it's been answered before).
Another way is to clone from a specific revision. Say checkin 6 was the mistake. You can clone your repository up to revision 5:
hg clone -r 5 myrepobad myrepoclean
now in myrepoclean you are back to where you were before the bad checkin. Obviously you need to be aware that anyone who has pulled the bad checkin is now liable to push it back in.
$ hg rollback --help
hg rollback
roll back the last transaction (dangerous)
This command should be used with care. There is only one level of rollback,
and there is no way to undo a rollback. It will also restore the dirstate at
the time of the last transaction, losing any dirstate changes since that
time. This command does not alter the working directory.
...
You should also look at the strip command.