Mercurial - get revision number if nodeid is known - version-control

I need to revert back to a particular revision.
For accomplishing the same, i am using the following command:
hg revert -r REV
(Reference - here)
But the problem is that even though i know the nodeid of that particular revision (the one to which i want to revert), but i do not know the revision number.
is there any way in which i could get the revision number(REV) from that nodeid?
Please help me out here - I am new to using Mercurial
Thanks in advance.

You need hg identify to answer your question and use -n to report back the local revision id:
hg identify -n -r <hash>
To make it really simple, most hg commands take both the local id or the global hash as valid identifiers so you could just use
hg revert -r <hash> --all
My followup question is this: Why are you reverting a changeset? To change your working directory to a particular point in the history you use
hg update -r <hash>
and then continue your development from there by creating a new (unnamed) branch.

Related

Update the working directory with part of a changeset

I've created a changeset which contains a number of individual changes. I've realized that one of those changes might not have been a good idea, and I'd like to update my working directory to include only part of that changeset to work on, without throwing out the changeset itself.
In git terms, I want to do something similar to git checkout -p HEAD~, or the similar
git checkout -b newbranch
git reset HEAD~
git add -p
git checkout -- .
How can I do this in Mercurial?
Read carefully hg help revert, pay special attention to -r option and NAME (ordinary list of fileset).
In your case (single changeset, part of which you want to eliminate from Working Dir), you have to:
hg up to the this changeset
hg revert -r "p1(.)" set:SOME-FILESET or, instead of fileset ("set:PATTERN" part), just "... FILE FILE2 FILE3 FILEN"
As result, you'll get in one readable command modified Working Directory with only needed part of changes in it

How do I see what I changed to resolve a mercurial merge conflict?

I just merged changes from our maintenance branch into our development branch. (We branch by cloning the mercurial repository, not with named branches.) There were a few conflicts, so I had to manually edit a half a dozen lines or so to resolve the merge conflict. No big deal. But when I look at the merge commit, I see the bazillion lines from the entire stack of patches against one parent or the other, not the merge conflict.
How can I review just the conflict and its resolution?
It sounds like you want the MergeDiff extension.
hg -n annotate probably?
Or, better annotate -n .. | grep 'hg tip --template "{rev}\n"'. You know changeset number of mergeset, your edits will have this number (automerged string will get number of latest change)
When I want to do this, I redo the merge with ui.merge=internal:merge so I get all the conflict markers. Then I diff it against the merge changeset. A bit clumsy, but it works.
You can use hg diff with the option -c:
-c --change REV change made by revision
Tip: use --stat to check only the files (with and without -c).

Hg (Mercurial): any way to "set aside" the working copy for later?

Scenario: After your last commit, you decided to do some extensive refactoring of the codebase. After a time, you realize it is taking longer than expected, and you'd really rather put off the refactoring for another time, and work on more pressing tasks. But you don't want to lose all of the refactoring work you've done so far.
So, is there a way to "archive" or "branch" the working copy (essentially, set it aside but keep it in the repository for later access), and then revert to the last good commit and resume from there, without fear of creating multiple heads or getting the two mixed up?
Don't worry about "the fear of two heads". Two heads is a very normal state. It's called anonymous branches, and it's one of the ways people do temporary branches in Mercurial.
Just commit, and then update to tip-1 and you're ready to go:
hg commit -m "working on XXX"
hg update -r "tip-1"
and away you go. If you want to drop a bookmark (less permanent than a tag) on that head you can, but there's no need to worry about it.
You can always push one head without pushing another using hg push -r HEAD where that can even be hg push -r .
Don't fear heads -- they're what makes a DAG based VCS powerful.
You can do this with the mq, attic or shelve extensions.
Assign a tag to your refactor revision
Commit the tag
Clone the repository again
Revert to the stable version
Work from the stable version
Don't worry about multiple heads, you can easily merge later
Since mercurial uses hard links, you can keep both repositories on your local machine with minimal space used.
commands:
$hg tag Refactor
$cd ..
$hg clone Refactor Stable
$cd Stable
$hg revert -r REVISION_NUMBER
extra help:
http://hgbook.red-bean.com/
http://kiln.stackexchange.com/
You can do it the simple way:
$ hg diff -g > tmp
$ hg revert --all
Your changes will now be stored in tmp. You can restore them with
$ hg patch --no-commit tmp
and you'll be back where you were. There are extensions like shelve that automates the above for you.
In git you would do a 'stash'. According to This hg has 'shelve', but it requires an extension.

Mercurial: How do you undo changes?

When using Mercurial, how do you undo all changes in the working directory since the last commit? It seems like this would be a simple thing, but it's escaping me.
For example, let's say I have 4 commits. Then, I make some changes to my code. Then I decide that my changes are bad and I just want to go back to the state of the code at my last commit. So, I think I should do:
hg update 4
with 4 being the revision # of my latest commit. But, Mercurial doesn't change any of the files in my working directory. Why not?
hg revert will do the trick.
It will revert you to the last commit.
--all will revert all files.
See the link for the Man Page description of it.
hg update is usually used to refresh your working directory after you pull from a different repo or swap branches. hg up myawesomebranch. It also can be used to revert to a specific version. hg up -r 12.
An alternative solution to hg revert is hg update -C. You can discard your local changes and update to some revision using this single command.
I usually prefer typing hg up -C because it's shorter than hg revert --all --no-backup :)
hg revert is your friend:
hg revert --all
hg update merges your changes to your current working copy with the target revision. Merging the latest revision with your changed files (=current working copy) results in the same changes that you already have, i.e., it does nothing :-)
If you want to read up on Mercurial, I'd recommend the very awesome tutorial Hg Init.
hg revert --all
and then
hg pull -u
works for me

Delete all local changesets and revert to tree

I'm using Mercurial and I've got into a terrible mess locally, with three heads. I can't push, and I just want to delete all my local changes and commits and start again with totally clean code and a clean history.
In other words, I want to end up with (a) exactly the same code locally as exists in the tip of the remote branch and (b) no history of any local commits.
I know hg update -C overwrites any local changes. But how do I delete any local commits?
To be clear, I have no interest in preserving any of the work I've done locally. I just want the simplest way to revert back to a totally clean local checkout.
When the simplest way (a new hg clone) isn't practical, I use hg strip:
% hg outgoing -l 1
% hg strip $rev # replace $rev with the revision number from outgoing
Repeat until hg outgoing stays quiet. Note that hg strip $rev obliterates $rev and all its descendants.
Note that you may have to first enable strip in your Mercurial settings.
PS: an even smarter approach is to use the revset language, and do:
% hg strip 'roots(outgoing())'
You'll want to make a local clone where you preserve only the changesets that are also present in the remote repository. Use TortoiseHg, hg log or similar to figure out which of your revisions is that lastest revision you didn't make (the one before the mess started). Using hg outgoing can help here -- it will list all the changesets you made -- pick a revision number earlier than any of those.
If the target revision is called good and your clone is called foo, then do:
hg clone -r good foo foo-clean
This will be a fast, local operation -- there is no reason to download everything again. The foo-clean clone will only contain changesets up to revision good. You can now replace foo-clean/.hg/hgrc with foo/.hg/hgrc in order to preserve your repository-local settings such as the default push/pull path.
When you are satisfied that foo-clean has everything you need from foo, then simply delete foo and rename foo-clean to foo. Do a hg pull to get any new changesets from the remote repository into your clone and continue like normal.
If nobody has pushed new changesets to the remote repository, then it is very simple to determine which revision you want to use as good above: hg id default will tell you the ID of the tip in the remote repository.
Ok. So just delete all the local stuff, hg init the new local repository and hg pull the latest tip you have. Don't forget to hg update after this.
You may use
hg strip revision
to kill any revision and its subtree in your local repository.
https://www.mercurial-scm.org/wiki/Strip
But don't try to use it for anything that has been already pushed.
Just delete everything you have on your local system and re-clone the remote repo.
hg strip `hg out --template "{rev} {author}\n" | grep YOUR_AUTHOR_NAME | cut -d " " -f 1`
does the trick for me.
It strips all revisions that aren't pushed to the default repository which are created with your author name.
You can also use this style to make it not checking with the default repository but with another Repository
hg strip `hg out OTHER_REPO_ALIAS --template "{rev} {author}\n" | grep YOUR_AUTHOR_NAME | cut -d " " -f 1`
If you are using TortoiseHg, one simple way to get out of a (small) mess is to first update to the latest revision, then select your changesets and initiate "merge with local". When the merge dialogue appears, simply click the little '+' icon to reveal some extra options, one of which is "discard changesets from merge target (other) revision". Doing this will mean your changesets will still be in the repo and get pushed, but will have no effect, because they will be discarded in the merge. If you have a lot of changesets spanning many heads, you might not want to pollute the repo this way, but it's a simple fix and worth considering if the changesets you are discarding contain data that you may later want to reference.