THG strip does not keep changes in the working directory - mercurial

I committed a changeset which is now in the "draft" Phase. It is the latest (local) revision. I want to remove that changeset and move all the changes back to the working directory. That means I want the opposite of committing it (which is working directory -> revision).
I tried the strip command with both keep and without. In both cases my changeset is removed but the changes are gone and the working directory is still empty. Then I need to unbundle the backup and pull it, at which point I'm exactly where I started with the local changeset in the history.
How do I move the changes from the committed changeset to the working directory? Maybe backout?
I'm using TortoiseHg but can also use the console there.

This doesn't directly answer the issue about the behavior of strip, but another way to do this in THG would be:
Shelve anything of value in your working folder
Update to the last-desired revision (the one before the revision you mean to undo)
Select the revision you want to undo and click "Revert All Files..."
Let it revert. The working folder will now match the revision you want to undo.
Strip (without "keep") the unwanted revision. Or even just leave it there and ignore it.

Looks like I managed to solve it, though I don't really understand how it works.
Following this answer I updated to my revision, switch to Ammend which showed the patch changes in the working directory as well as the revision, then strip with keep removed the revision, only the working directory now contains the files because of Ammend.

Related

How to recover an hg shelve when its parent (or an ancestor) has been removed/stripped?

I seem to have made a mistake when performing a series of rebase, strip, and shelve operations. The result is that I am unable to unshelve. When I run hg unshelve in the current state, it just throws an ugly error:
# hg unshelve
unshelving change 'repo-02'
abort: 00changelog.i#5bd4b71e0176: unknown parent!
I think what has happened is that after shelving a change (or maybe a series of shelves) I stripped / rebased away a commit which was a dependency of the shelf.
The shelf has changes to a number of "random" files - meaning their changes are unrelated (mainly temporary debug output, things like that). So even with the single stripped file gone, the remaining parts of the shelve should be OK to use - but how can I get past this error?
One method of getting around this might be to undo the stripped changesets. But before I did that I found another method which worked, and I think this was ultimately simpler as I had a large # of strip backups to work through.
Looking in the .hg\shelved\ folder I actually had data files from several shelve 'events'. They looked something like this:
repo-01.hg
repo-01.patch
repo-01.shelve
repo-02.hg
repo-02.patch
repo-02.shelve
repo.hg
repo.patch
repo.shelve
Reading these file contents I noticed that the .patch files were indeed standard diff-style patches.
Also by looking at the contents of all 3 shelves I could determine that it was only the "repo.patch" (the oldest one) that I actually needed.
(Initially I tried removing the 01 and 02 files and unshelving, but this produced a different error, so I reversed course.)
I then ran:
hg patch --no-commit repo.patch
from within that folder. This basically worked fine, and now my working folder contained modified files again, and they checked out as having the expected contents.
Interestingly because of the original mistake (stripping a commit) one of the files in that patch failed to apply - because the file no longer exists. But fortunately hg patch was resilient enough to just skip over this. Since the file was deleted intentionally, this was not a problem.
Following the above, I used:
hg shelve --cleanup
to get rid of the messy state. Shelve / unshelve now work normally again.

How to revert a file to an earlier version in Mercurial?

I made some changes to a file and committed it. (In fact there were several commits).
Then I wanted to revert to the earlier version and lose all those changes.
I did something like:
hg update -r nnn where nnn was the reversion number of the changeset I wanted to go back to.
That worked. I was happy.
Then, later, I had to push my local repository to the remote. But when I did hg push I got a message about there being two heads on this branch and one of them not being known to the remote repositiory. It suggested I merge before pushing. (I think).
I googled this and found a page that suggested I do "hg merge". I did that. Now the resultant file is back to where I started. I.e. it contains all the changes I wanted to throw away.
Where did i go wrong?
EDIT:
I have found this post Mercurial — revert back to old version and continue from there
where it says:
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.
That sounds like my case. Something went wrong at the merging stage it seems. Was I on the wrong branch when I did "hg merge"?
You're past this point now but if it happens again, and it's just a single file you want to revert then consider:
hg revert --rev REVISION_YOU_LIKED path/to/just/one/file.txt
That doesn't update you whole repository to a different revision, and it doesn't create any commits. It just takes a single file in your working directory and makes it look like it used to. After doing that you can just commit and you're set.
That's not the way to go if you want to undo all the changes you've made to all files, but for reverting a single file use revert and avoid multiple heads and merging entirely.
No, nothing went wrong at the merge stage – Mercurial did exactly what you asked it to...
What merge means is that you take the changes on your current branch, and the changes on the 'other' branch, and you merge them. Since your original changes were in the 'other' branch, Mercurial carefully merged them back into your current branch.
What you needed to do was to discard the 'other' branch. There are various ways of doing that. The Mercurial help pages discuss the various techniques, but there are pointers in other SO questions: see for example Discard a local branch in Mercurial before it is pushed and Remove experimental branch.
(Edit) Afterthought: the reason you got a warning about there being two heads on the branch is because having two heads is often a temporary situation, so pushing them to a remote repository is something you don't want to do accidentally. Resolutions are (i) you did mean to push them, so use --force to create two heads in the remote repository; (ii) ooops!, you meant to merge them before pushing, so do that; or (iii) ooops!, you'd abandoned the 'other' one, so get rid of it. Your case was (iii).

Mercurial - why can't I find deleted files?

I recently let the IDE replace a trivial text in the entire project, and recognized that mistake only after committing other changes to Mercurial. I panicked and (knowing very little about Mercurial, now after having read the definitive guide starting to get to know it better) tried every command that seemed to make my mistake "go away". It goes without saying that this was a move I am not proud of.
Of the things I remember to have tried was hg update tip and hg rollback. Since I'm using Mercurial on my local machine only and do not pull or push from any other repository, I think these commands did not cause my main problem: There are a lot of files missing now -exactly the files I let the IDE make the wrong replacements in.
What bothers me is that I have done hg status --change REV to find all files changed in a revision, and the deleted files do not show up there.
PHPStorm has a local history, which shows which files are now missing. That (only that?) enables me to hunt down the individual files and revert to their last known revision:
hg log -l 1 path/to/foo.txt
hg revert -r <my revision> path/to/foo.txt
... but that is way too time-consuming for the hundreds of files that got changed. Please tell me there's a better way. The PHPStorm history is nice and can restore the files as well, but it will restore them to the point where they had already been erroneously changed.
Your help is greatly appreciated, and I vow to learn & appreciate Mercurial as more than just a context menu item starting today.
If you are willing to lose the changes that were committed with or since the error, you may be able to go back to the revision just before the error, and start working from there. Use hg log to find out which revision you need, and hg update --rev XX to go to that revision. If you're not sure which revision you want, update to various revisions and take a look.
Once you have updated to the correct revision, you can just continue working from there. The next time you commit, you will automatically create a new branch on which you'll be working, which will not have the error in it. If you want, you can go back to the original branch and close it.
You might even be able to get back any correct commits that happened after you committed the error up to the revision you rolled back to. On the old branch, identify the revision after the error, and do a diff between that revision and the tip of that branch. Then, see if you can apply the diff as a patch on your new branch. You will still lose any changes that were in the same commit as the error, though.

Is there a way in Mercurial/TortoiseHg to remove a changeset while keeping its changes in the working copy?

Like the title says. I essentially want a way to make Mercurial "forget" a changeset in the local repository. Obviously, this would only work for changesets which had not been pushed without also reverting the original changeset.
Mercurial doesn't make forgetting anything easy -- no commands that are destructive of history are enabled by default. Without enabling any extensions the easiest way to do this would be:
hg clone -U -r LAST_CHANGE_YOU_WANT your-repo new-repo
and then replace the .hg in your-repo with the one from new-repo.
In this case specifically, I was trying to move changes between branches when the normal merge wouldn't work, so I used MQ, however I wanted the changes to remain in the working copy rather than accidentally getting pushed. It looks like one can do what I wanted with hg import --no-commit, which TortoiseHg does not currently (but should soon) provide any UI for.

Mercurial how to rollback to a tag?

I am a little confused about how to rollback to a tag in Mercurial. (which I am very new to)
Say I have a tag called "Version-1.0" which was several revisions ago. lets say we are at r400 now
Now if my managers were to tell me they don't like the direction things have been going and basically want to ditch everything since that tag and go back to Version-1.0.
Well I can checkout that tag with:
hg update -r Version-1.0
Ok so now I am back to the version 1.0 tag, and if I were to never need to make a change this would be fine. However, as soon as I make a change and commit, I now have 2 heads (my new changes to Version-1.0 and r400 the stuff the managers want to ditch).
So now I need to merge with r400. I don't want to. (I don't really want to wipe all those changes off the earth, I would like them to remain in my history so I can go back to them later if management changes their mind again) but I currently don't want any of them.
What do I do?
update
An answer stated:
You could clone the entire repository up until the tag, then use that clone as your "new" central repository.
If my central repository is hosted by bitbucket, I am not sure how to do this. If the current one is at URL https://jisaacks#bitbucket.org/jisaacks/hgml and I want to clone it up to the tag to a new repo named hgml2 (that doesn't exist yet) I tried this command locally on my machine:
hg clone -r Version-1.0 https://jisaacks#bitbucket.org/jisaacks/hgml https://jisaacks#bitbucket.org/jisaacks/hgml2
I get this error:
abort: cannot create a new http repository
Log on onto bitbucket and click the "Fork" arrow icon in the upper right corner. Now you can open the "advanced settings" to fork from a tag.
You could then rename the first repository to something like "myproject-abandoned-foo-changes" and reuse the original name for the forked repository, where you will continue development.
edit: you could also do a no-op merge. The linked wiki page explains that this might be bad because your history will be contaminated with the unwanted changes, but I think in your case this might be exactly what you want as it would preserve your changes while avoiding the "switching everything to a new repo" issue you complain about.
You can use hg revert. The following command restores your repository to a certain tag and discards all local changes.
hg revert -r tagname --all
The "correct" way to do this in modern Mercurial is to close the branch:
hg up head-i-dont-like
hg commit --close-branch
While this was originally added to close named branches, it works equally well with anonymous branches (what the OP has). In particular, it will only affect the head it is committed on, and not any other heads on the same named branch.