53

I'm just getting started with Mercurial, and I've come across something which I don't understand.

I made changes to several files, and now I want to undo all the changes I made to one of them (i.e. go back to my last commit for one specific file).

As far as I can see, the command I want is revert.

In the page I linked to, there is the following statement:

This operation however does not change the parent revision of the working directory (or revisions in case of an uncommitted merge). To undo an uncomitted merge, you can use "hg update -C -r." which will reset the parents to the first parent.

I don't understand the difference between the two (hg revert vs. hg update -C -r). Can anyone enlighten me as to the difference? And in my case, do I really want the revert or the update to go get rid of the changes I made to the file?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Edan Maor
  • 9,772
  • 17
  • 62
  • 92
  • To really see the difference, you should try with `revert -r`, then use hg status, you'll see the difference :) – tonfa Mar 24 '10 at 11:05

1 Answers1

66

The first difference is revert can work on a subset of the working copy while update works on the whole working copy. the other difference is in what happens when you want to go back to a version other than the last committed one.

if we have revisions (caps are committed, lower case are changes in the working copy, parent revision is C )

A-B-C-d

update -C -r B will give you

A-B-C

with your working copy set to B, any changes will result in branching from B (parent revision set to B)

A-B-C
  \e

revert -r B will give you

A-B-C-b'

where b' is a set of changes which undoes everything in the intermediate committed changes, in this case it undoes all of C. any changes now just join the b' set (parent revision left unchanged at C)

jk.
  • 13,817
  • 5
  • 37
  • 50
  • 6
    Your explanation of how reverting/updating to a revision other than the latest is excellent. Let me just add that the sentence in the help that mentioned this distinction is "does not change the parent revision of the working directory". In jk's examples the "parent revision of the working directory" starts out as C. With the update it ends up as B, and with the revert it is still C ("does not change"). In either case it can be viewed with "hg parents". Also, the "revert can work on a subset of the working copy' comes from this -- the is only one working dir parent, and all files share it. – Ry4an Brase Mar 24 '10 at 12:44
  • Cool, great answer to an oft asked question. – Ry4an Brase Mar 24 '10 at 13:38
  • 4
    Thanks, great answer. Just one clarification: you wrote (last line) "will give you A-B-C-b', where b' is a set of changes which undoes everything in the intermediate commited changes, in this case it undoes all of C. any changes now just join the b' set (parent revision left unchanged at C)". If I understand correctly, you're just left with a working directory containing the B revision, but your parent is C, so if you commit now, you'll basically have a tree that is "A-B-C-B'" (where B' is exactly the same as B). In other words, the history up to B' stays exactly the same? – Edan Maor Mar 24 '10 at 15:41
  • 1
    yes, mercurial doesn't usually allow you to alter history, hence to revert to a previous changeset you have a new changeset which undoes everything. so the working copies would look the same (both like B) but the B changeset would be different to the B' changeset – jk. Mar 24 '10 at 16:18
  • and of course update doesn't change history with respect to the branch that has happened, it just allows you to start a new historical branch, sort of – jk. Mar 24 '10 at 16:23