Mercurial hg Subrepository issue - "abort: unknown revision' - mercurial

Note: I asked this yesterday over at kiln.stackexchange.com, but haven't gotten an answer, and it's holding up my work. So I figured I'd give it a shot here.
My main mercurial repository has a bunch of subrepositories in it. During initial setup, I made a mistake in my .hgsub. Namely, I pointed two subrepositories to the same directory.
What I should have had:
sites/1=sites/1
sites/2=sites/2
sites/3=sites/3
What I actually had:
sites/1=sites/1
sites/2=sites/2
sites/2=sites/3
Stupid copy/paste error. I committed the incorrect .hgsub, not realizing my error. A few revisions later, while adding a some new subrespositories to .hgsub, I noticed the mistake and fixed it inside .hgsub. I committed and kept rolling along. I've committed a reasonable amount of work that I'd prefer not to redo since I 'fixed' the mistake in .hgsub.
Now we come to the actual problem: I've made some changes inside the subrepository sites/3, and when I try to commit the main repository, I get the following error:
abort: unknown revision 'LongGUIDLookingString'
I found this discussion, which seems to address the same problem I'm having, but I can't quite work out how bos fixed it. What do I need to do in order to fix this?
Relevant section of .hgsubstate:
7d1e430ac5f12e00cb5bebcdf693e72db2c45732 sites/1
6eea936a5b7cfff6169f59d0dc1c8c4eb5f8412d sites/2
e2b83b301997de8add1b659d82a7ab8201bda653 sites/3

I'd guess the .hgsubstate file now contains a hashid (which is what your LongGUIDLookingString is) from repo3 in the repo2 entry.
Try editing .hgsubstate to point to a correct/present hashid for each repo.
If that doesn't work, please paste i your .hgsubstate file so we can see how it can be tweaked.

For those who struggle committing changes to .hgsubstate, it appears that:
hg commit -i is not working while
hg commit -m does.

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.

How to re-commit last changeset with a different comment?

As I understand it, you can't really fix a comment in Hg. So what I would like to do instead is re-push the exact same changes (or at least "touch" the same files and commit & push again).
The reason this is necessary is because we have a bug tracking and build system that relies on specific comment patterns, and we need to make sure the right files get included in the build, but if I forget to update the bug # in my comment from my last commit, and I accidentally commit and push it under the wrong # because i'm overzealous, how can I re-push those same files again without manually going into each one and adding a space or line break just to create a diff?
To clarify, I can't "rollback" or something; it's already been pushed with the wrong message.
As far as I know, current Mercurial features provide no support for this. After the changeset has been pushed, there's little you can do to un-push it, besides stripping it from the server repo and any other developer's repo.
I guess you you should ask those who set up this workflow in your shop; they should've come up with some exception handlers for it.
We usually just ignore issues like this, and close the bug by hand, making sure the bug links to the correct changeset. If the changeset is really messed up (usually this means bad changes, not a malformed commit message), we resort to stripping.
Since your change has already been pushed you can't use a simple fix, like "hg commit --amend", but you can do something similar. Basically, the following commands re-do the commit with Mercurial's help:
CSET=...the changeset to re-do...
hg up -r "p1($CSET)" # Update the working directory to the parent revision
hg log -r "$CSET" -p > changes.patch
hg import --no-commit changes.patch
hg commit # And use the appropriate commit message.
Then, merge and push.
The only way that I could think of doing this is to commit two more changes, one would be an hg backout of the incorrect revision and the other would be an hg backout of that revision with the corrected comment.
I don't like that idea though and wouldn't recommend it if there was any way to fix the problem in your bug tracking system.

Mercurial: R with 'hg status', how to commit?

If I do 'hg status' and see the following:
R flash/AC_OETags.js
it seems to mean that there is no file there, but there has been one at some point that has been removed.
How do I 'commit' this change so it stops showing up when I do 'hg status'?
==UPDATE==
The answer seems to be to commit the file. Actually, there are ~100 files with status R because I removed an entire directory tree. Anyone know how to commit all files in a directory tree in one go?
I don't want to do just hg commit, because there are other changes too.
The “R” means “Removed” so the next time we commit in Mercurial this file will be removed. (The history of the file will remain in the repository, so of course we can always get it back).
therefore run your hg commit command and all will be well
Thanks to hginit.com for that titbit - its my Mercurial bible
You can commit just that file:
hg commit flash/AC_OETags.js
however having "masses of other uncommitted files" is terrible process. You need to come up with a workflow that lets you commit frequently.
You can use the repository explorer from TortoiseHg to easily manage the files you want to include in a commit.
Also, removing a directory probably warrants a changeset in itself. You should get into the habit of committing more often (one concept, one commit... and it's local anyway). Furthermore, as long as you haven't pushed your changes to anyone (or anyone pulled from you) you could still use hg rebase --collapse to regroup some changesets if you think you have separated too much (this is a more advanced feature that I suggest you try on a test repository first as you could break things if you're not careful)