Mercurial — revert back to old version and continue from there
Asked Answered
L

7

254

I'm using Mercurial locally for a project (it's the only repo there's no pushing/pulling to/from anywhere else).

To date it's got a linear history. However, the current thing I'm working on I've now realized is a terrible approach and I want to go back to the version before I started it and implement it a different way.

I'm a bit confused with the branch / revert / update -C commands in Mercurial. Basically I want to revert to version 38 (currently on 45) and have my next commits have 38 as a parent and carry on from there. I don't care if revisions 39-45 are lost for ever or end up in a dead-end branch of their own.

Which command / set of commands do I need?

Lintwhite answered 29/3, 2010 at 18:53 Comment(1)
For anyone interested, this has popped up on the related sidebar which is a great explanation of revert vs update: #2507303Lintwhite
C
152
hg update [-r REV]

If later you commit, you will effectively create a new branch. Then you might continue working only on this branch or eventually merge the existing one into it.

Congenital answered 29/3, 2010 at 18:56 Comment(4)
next commit will create a new branch. If you are unsure, just make a backup of you repository (with working copy), try it out - do not like the outcome -> start from scratch at no costCongenital
This is a dubious answer as it merges your current changes with the old revision which is probably what you do not want to do. The correct answer should be hg revert.Brufsky
The answer is fine, except the bit about merge (I do not think the questioner will want to merge).Crumpet
@NeonWarge REV is simply a placeholder for the revision. It can be its number, its hash, a bookmark and so on. Trevor: this is not dubious because it doesn't merge anything. No need to.Roush
S
409

Here's the cheat sheet on the commands:

  • hg update changes your working copy parent revision and also changes the file content to match this new parent revision. This means that new commits will carry on from the revision you update to.

  • hg revert changes the file content only and leaves the working copy parent revision alone. You typically use hg revert when you decide that you don't want to keep the uncommited changes you've made to a file in your working copy.

  • hg branch starts a new named branch. Think of a named branch as a label you assign to the changesets. So if you do hg branch red, then the following changesets will be marked as belonging on the "red" branch. This can be a nice way to organize changesets, especially when different people work on different branches and you later want to see where a changeset originated from. But you don't want to use it in your situation.

If you use hg update --rev 38, then changesets 39–45 will be left as a dead end — a dangling head as we call it. You'll get a warning when you push since you will be creating "multiple heads" in the repository you push to. The warning is there since it's kind of impolite to leave such heads around since they suggest that someone needs to do a merge. But in your case you can just go ahead and hg push --force since you really do want to leave it hanging.

If you have not yet pushed revision 39-45 somewhere else, then you can keep them private. It's very simple: with hg clone --rev 38 foo foo-38 you will get a new local clone that only contains up to revision 38. You can continue working in foo-38 and push the new (good) changesets you create. You'll still have the old (bad) revisions in your foo clone. (You are free to rename the clones however you want, e.g., foo to foo-bad and foo-38 to foo.)

Finally, you can also use hg revert --all --rev 38 and then commit. This will create a revision 46 which looks identical to revision 38. You'll then continue working from revision 46. This wont create a fork in the history in the same explicit way as hg update did, but on the other hand you wont get complains about having multiple heads. I would use hg revert if I were collaborating with others who have already made their own work based on revision 45. Otherwise, hg update is more explicit.

Statis answered 2/4, 2010 at 9:50 Comment(5)
AWESOME answer. I used hg revert --all --rev ## and it saved my ass :DMendacious
Wouldn't it be better to also close the branch of the dangling head? This would prevent future warnings on the repository. See https://mcmap.net/q/111494/-abandoning-changes-without-deleting-from-historyDeclarer
note: hg revert --all --rev xxx will modify local files needed to revert from where you are in your local repo. So you need to update before to where you want to revert from.Ideation
To branch off an earlier version, I first had to do a revert, and then an update. That being said, a less opaque explanation than most.Stempson
Almost afraid to ask, but how do I figure out the revision number of the desired commit/ revision?Aforementioned
C
152
hg update [-r REV]

If later you commit, you will effectively create a new branch. Then you might continue working only on this branch or eventually merge the existing one into it.

Congenital answered 29/3, 2010 at 18:56 Comment(4)
next commit will create a new branch. If you are unsure, just make a backup of you repository (with working copy), try it out - do not like the outcome -> start from scratch at no costCongenital
This is a dubious answer as it merges your current changes with the old revision which is probably what you do not want to do. The correct answer should be hg revert.Brufsky
The answer is fine, except the bit about merge (I do not think the questioner will want to merge).Crumpet
@NeonWarge REV is simply a placeholder for the revision. It can be its number, its hash, a bookmark and so on. Trevor: this is not dubious because it doesn't merge anything. No need to.Roush
P
32

I just encountered a case of needing to revert just one file to previous revision, right after I had done commit and push. Shorthand syntax for specifying these revisions isn't covered by the other answers, so here's command to do that

hg revert path/to/file -r-2

That -2 will revert to the version before last commit, using -1 would just revert current uncommitted changes.

Puberty answered 9/4, 2013 at 10:16 Comment(2)
I do find this extremely useful. Of course for -r option you can simply provide the revision numberRive
You can also select a specific revision. e.g. hg revert path/to/file -r478Portugal
L
8

IMHO, hg strip -r 39 suits this case better.

It requires the mq extension to be enabled and has the same limitations as the "cloning repo method" recommended by Martin Geisler: If the changeset was somehow published, it will (probably) return to your repo at some point in time because you only changed your local repo.

Lordosis answered 14/10, 2013 at 8:21 Comment(1)
Didn't know about this one. Easier and cleaner than deleting and re-cloning the repo. Thanks.Isreal
M
6

After using hg update -r REV it wasn't clear in the answer about how to commit that change so that you can then push.

If you just try to commit after the update, Mercurial doesn't think there are any changes.

I had to first make a change to any file (say in a README) so Mercurial recognized that I made a new change, then I could commit that.

This then created two heads as mentioned.

To get rid of the other head before pushing, I then followed the No-Op Merges step to remedy that situation.

I was then able to push.

Muhammadan answered 16/8, 2013 at 21:54 Comment(1)
you can do a commit --close-branch on the old branch. You can also push -f to push new heads, but this can cause confusion as to which it the current one.Crumpet
P
5

The answers above were most useful and I learned a lot. However, for my needs the succinct answer is:

hg revert --all --rev ${1}

hg commit -m "Restoring branch ${1} as default"

where ${1} is the number of the revision or the name of the branch. These two lines are actually part of a bash script, but they work fine on their own if you want to do it manually.

This is useful if you need to add a hot fix to a release branch, but need to build from default (until we get our CI tools right and able to build from branches and later do away with release branches as well).

Plagioclase answered 25/3, 2016 at 15:56 Comment(0)
A
1

I'd install Tortoise Hg (a free GUI for Mercurial) and use that. You can then just right-click on a revision you might want to return to - with all the commit messages there in front of your eyes - and 'Revert all files'. Makes it intuitive and easy to roll backwards and forwards between versions of a fileset, which can be really useful if you are looking to establish when a problem first appeared.

Alanna answered 26/10, 2017 at 11:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.