views:

525

answers:

2

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?

Thanks

A: 

update updates the working copy of your repository to the current working tip if no arguments are passed. It is conceivable that you set up a HG repo on a remote server, push thousands of revisions and no files appear in the directory. If you typed hg update on the server, you'd see a copy of everything as they are supposed to be in the current tip.

The optional switches in update let you update (up to) a specific changeset. -C is destructive to your current copy in that respect, but not immutable. I.e. you can just update back to the tip.

revert simply reverts the tip to a prior revision, thereby moving the tip backwards in time. I.e., throw out that revision, its toxic.

Tim Post
+13  A: 

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

if we have revisions (caps are commited, lower case are changes in the working copy, parent revison 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 bracnhing 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 commited changes, in this case it undoes all of C. any changes now just join the b' set (parent revision left unchanged at C)

jk
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
good point, added what the parent revision is at each point
jk
Cool, great answer to an oft asked question.
Ry4an
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
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
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