6

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...

Javier Novoa C.
  • 11,257
  • 13
  • 57
  • 75
  • I don't understand how the graph log could look like that. You can't merge `b` with `c` since `c` is an ancestor of `b`. How did you end up with the `a` changeset? Is it really a merge? Or is there more changesets involved that you left out? – Lasse V. Karlsen Feb 10 '12 at 22:27
  • Let me rephrase that. There seems to be no point in the merge since the linear history would go `d`-`c`-`b`-`a`, no need to merge `c` and `b` at all. – Lasse V. Karlsen Feb 10 '12 at 22:28

2 Answers2

6

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.

Community
  • 1
  • 1
Christian Specht
  • 35,843
  • 15
  • 128
  • 182
2

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!

Ry4an Brase
  • 78,112
  • 7
  • 148
  • 169