Mercurial_ The Definitive Guide - Bryan O'Sullivan [62]
If you’ve pushed a change to another repository—particularly if it’s a shared repository—it has essentially “escaped into the wild,” and you’ll have to recover from your mistake in a different way. If you push a changeset somewhere, then roll it back, then pull from the repository you pushed to, the changeset you thought you’d gotten rid of will simply reappear in your repository.
(If you absolutely know for sure that the change you want to roll back is the most recent change in the repository that you pushed to, and you know that nobody else could have pulled it from that repository, you can roll back the changeset there, too, but you really should not expect this to work reliably. Sooner or later a change really will make it into a repository that you don’t directly control [or have forgotten about], and come back to bite you.)
You Can Only Roll Back Once
Mercurial stores exactly one transaction in its transaction log; that transaction is the most recent one that occurred in the repository. This means that you can only roll back one transaction. If you expect to be able to roll back one transaction and then its predecessor, this is not the behavior you will get.
$ hg rollback
rolling back last transaction
$ hg rollback
no rollback information available
Once you’ve rolled back one transaction in a repository, you can’t roll back again in that repository until you perform another commit or pull.
Reverting the Mistaken Change
If you make a modification to a file, and decide that you really didn’t want to change the file at all, and you haven’t yet committed your changes, the hg revert command is the one you’ll need. It looks at the changeset that’s the parent of the working directory, and restores the contents of the file to their state as of that changeset. (That’s a long-winded way of saying that, in the normal case, it undoes your modifications.)
Let’s illustrate how the hg revert command works with yet another small example. We’ll begin by modifying a file that Mercurial is already tracking.
$ cat file
original content
$ echo unwanted change >> file
$ hg diff file
diff -r 68bfacc0125f file
--- a/file Tue May 05 06:44:36 2009 +0000
+++ b/file Tue May 05 06:44:36 2009 +0000
@@ -1,1 +1,2 @@
original content
+unwanted change
If we don’t want that change, we can simply hg revert the file.
$ hg status
M file
$ hg revert file
$ cat file
original content
The hg revert command provides us with an extra degree of safety by saving our modified file with a .orig extension.
$ hg status
? file.orig
$ cat file.orig
original content
unwanted change
* * *
Be careful with .orig files
It’s extremely unlikely that you are using Mercurial to manage files with .orig extensions or that you even care about the contents of such files. Just in case, though, it’s useful to remember that hg revert will unconditionally overwrite an existing file with a .orig extension. For instance, if you already have a file named foo.orig when you revert foo, the contents of foo.orig will be clobbered.
* * *
Here is a summary of the cases that the hg revert command can deal with. We will discuss each of these in more detail in the section that follows.
If you modify a file, it will restore the file to its unmodified state.
If you hg add a file, it will undo the “added” state of the file, but leave the file itself untouched.
If you delete a file without telling Mercurial, it will restore the file to its unmodified contents.
If you use the hg remove command to remove a file, it will undo the “removed” state of the file, and restore the file to its unmodified contents.
File Management Errors
The hg revert command is useful for more than just modified files. It lets you reverse the results of all of Mercurial’s file management commands—hg add, hg remove, and so on.
If you hg add a file, then decide that in fact you don’t want Mercurial to track it, use hg revert to undo the add. Don’t worry;