30

Say I have files File_A, File_B and File_C. I edit File_A and File_B on purpose but File_C I just added some debugging code that I don't plan to commit. Then by accident I do a

hg commit -m "comment"

How do just revert/rollback/backout File_C? Basically I'd be happy to be able to go

hg update -r <oneRevBack> File_C
hg commit -m "put C back"

but update doesn't take a filter AFAIK so it's also going to revert File_A and File_B. I can copy File_C somewhere, hg update, then copy it back but that seems lame. Is there a way to do this directly in Mercurial?

Martin Geisler
  • 72,968
  • 25
  • 171
  • 229
gman
  • 100,619
  • 31
  • 269
  • 393
  • 1
    Revert / rollback and / backout are all entirely separe things. Revert = change in working directory but not repository, rollback = uncommit, and backout = negate the commit. The answer ranges from impossible (rollback) to easy (backout) depending on what you want. – Ry4an Brase Feb 24 '11 at 15:05

5 Answers5

35

The exact command you wanted to use would have worked if you used hg revert instead of hg update

hg revert -r .^ File_C
hg commit -m "put C back"
qwertzguy
  • 15,699
  • 9
  • 63
  • 66
Den
  • 866
  • 6
  • 6
8

In most cases VonC's solution is just perfect. However, if rollback is no option (e.g. because the commit in question is not the last one or because you did a complex partial commit), then you can do a new commit with the reversed diff of the unwanted changes to File_C:

hg diff -c REVISION --reverse File_C | hg import -m "Revert changes to File_C" -

Where REVISION refers to the commit where File_C has been committed accidentally. The first command produces the reversed diff for the file in question. It's output is piped to hg import (don't forget the trailing -).

UPDATE: You can also use the backout command:

hg backout -I File_C REVISION
hg commit -m "Revert changes of File_C in REVISION" File_C

The backout command changes your working copy in that it undoes the changes to File_C commited in rev. REVISION. Afterwards the revert is committed explicitly.

Oben Sonne
  • 9,893
  • 2
  • 40
  • 61
  • backout automatically commits. You can skip that line as I did in my answer. – Ry4an Brase Feb 24 '11 at 15:42
  • 1
    @Ry4an: `backout` only commits automatically if the revision to backout is the parent of the working dir - here a simple `rollback`, as suggested by *VonC*, usually does the job. In other cases (which I refer to in may answer) one needs to commit explicitly. However, thanks for the hint, I'll update my answer to distinguish these backout situations. – Oben Sonne Feb 24 '11 at 19:15
  • ah, good to know. I thought it always committed but didn't always merge leaving two heads if the backed out cset wasn't the parent. – Ry4an Brase Feb 24 '11 at 20:35
  • @Ry4an: Yep, it worked like that (leaving 2 heads) before Mercurial 1.7, now the backout command has a slightly (?) different behavior. – Oben Sonne Feb 25 '11 at 06:43
  • After the backout how do I get the changes back on the local copy? I accidentally committed and pushed changes to a bunch of files whose changes I didn't want to commit. So I backed out the commit, but how do I get those files back to the modified state they were in before my accidental commit? – Matt Oct 31 '17 at 15:19
3
hg revert FILE -r REVISION

you can revert it to last commit via

hg revert FILE -r .~1
3

You could use hg rollback to undo your last commit, and then re-do it again, this time without the file C.
(as mentioned in Mercurial FAQ, and also in this FAQ entry where it is noted that "there is no backup when you rollback a transaction", so use it with caution)

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
0

You can also use interactive mode:

hg revert -i -r .^

Select what you want reverted and confirm.

hg amend
John Smith
  • 363
  • 3
  • 13