Mercurial: Unable to unshelve shelved changes - mercurial

It seems like ShelveExtension only shelves your modified files leaving untracked or deleted.
I am new to Mercurial and coming from git so for me this is not expected.
Even bigger problem I am not able to hg unshelve with what I assume is an error message.
See below:
unshelving change 'main'
temporarily committing pending changes (restore with 'hg unshelve --abort')
rebasing shelved changes
abort: uncommitted changes
Is that an expected behavior and I am just missing something?
How could I unshelve my modified files without restoring/committing/etc.?
Is there an extension which behaves exactly like git stash?
Steps to reproduce:
Environment:
OS: Windows 8
Mercurial: Mercurial Distributed SCM (version 3.0.1).
Installed as cygwin /usr/bin/hg (Tortoisehg is not installed, Windows hg is installed but not used)
Extension: ShelveExtension.

Is that an expected behavior and I am just missing something?
Yes, this is normal behavior. You need to do hg addremove (or manually hg add and hg rm the individual files) if you want Mercurial to track file creation and deletion. Renaming should be done with hg mv. This is vaguely similar to git add, except that you do not need to do it for modified files.
When you unshelve, your working directory should be clean. At the very least, it should not have any missing files (prefixed with ! in hg st) nor any modified files (prefixed with M). You can always make a temporary commit and hg strip it later.
How could I unshelve my modified files without restoring/committing/etc.?
There's no sane way to do this in the general case. What if the shelf contains changes to a file which no longer exists? If the file deletion had been committed, you could generate a patch conflict, and that's what Mercurial does. But without a commit to conflict with, there's no obvious response to this situation.
Is there an extension which behaves exactly like git stash?
Not to my knowledge, but this is beyond the scope of StackOverflow.

Related

How to rename a file using Mercurial Queues?

Mercurial Queues is about patches, and patches know nothing about file renames. Is this the reason why Mercurial Queues don't support file renames, or am I doing something wrong renaming the file? I have worked on a patch queue modifying just one file called foo. Now I go back to patch 4 and rename the file via hg mv:
hg qpop 4 # Unapply all patches until patch 4.
hg mv foo bar # Rename file and led Mercuial know about it.
hg qrefresh # Should apply changes to unapplied patch 4.
hg qpush -a # Should apply all unapplied patches.
I get the following error:
unable to find 'foo' for patching
1 out of 1 hunks FAILED -- saving rejects to file foo.rej
patch failed, unable to continue (try -v)
patch failed, rejects left in working dir
errors during apply, please fix and refresh 5.diff
So how should I do to handle file renames with Mercurial Queues? Mercurial commits handle file renames for a reason (as without, it would lose the whole history about the editing of the file after renaming).
Update
Just noticed that hg histedit folding changesets and hg collapse also lose the information of file renaming, the file shows up as a new one instead of a renamed one, and I guess this is for the same reason. Seems like collapsing private changesets is not possible in Mercurial without loosing that information?
Update 2
Found out collapsing private changesets without loosing rename information is possible with hg rebase and its --collapse option, e.g. hg rebase -s 5 -d 4 --collapse. The issue that the other commands should sostain rename information is still vacant, but using the hg rebase command there is at least a way to achieve the desired result.
Is this the reason why Mercurial Queues don't support file renames,
no.
or am I doing something wrong renaming the file?
no.
Yes, patches in chain will have troubles, if they was prepared for foo file, but later in will be bar, but due to different reasons: patches are independent, and every and each patch know nothing about changes in others - they work with context, not with sequence of operations in separate patches. You done rename correctly, but this changeset invalidates later changesets, prepared on old content

Apply mercurial bundle file on different changeset

TLDR: I have an HG bundle with parent X, but revision X does not exist in my repo. However, I am sure that the files of revision Y are identical to revision X. How do I apply the bundle?
Background:
I use hgsubversion to interact with an SVN repo.
There were some changes I did not want to commit. hgsubversion does not support partial pushes.
I used to workaround by manually creating temporary exports/patch files, or manually restoring .orig files (result of hg revert).
In this case I committed the changes I did not want to push, then used hg strip, then pushed, then tried to use hg unbundle .hg/strip-backup/file.
Problem: hgsubversion replaces the original changeset with a new one it imports from SVN after it's committed it. Result: the changeset ID changes. This is a problem because now hg unbundle no longer works, as it relies on the parent changeset being there (but it's been stripped).
Ironically, hgsubversion itself uses strip and thus has a backup file I can use to strip the new rev, add the stripped old revision, then apply the bundle with my revisions, export the patch, strip both, and restore the SVN revision. But this sounds... extremely painful and stupid. Is there nothing better I can do?
(hg transplant doesn't seem to like the bundle without having the parent in the repo, either)
It's effectively impossible to use a bundle without the bundle's precise parent changesets. Bundles consist of compact binary deltas that can only be applied to the precise binary source. There is no 'context' available that would allow Mercurial to guess how to apply them to other revisions the way patch does. In core Mercurial, this is never an issue because changesets are never removed, but extensions like hgsubversion and mq break the rules.
(If you can recover the stripped changesets from a backup bundle in .hg/strip-backup, you can then rebase your changes and strip again.)
Background: After hitting an issue with hgsubversion pushing only 1 revision successfully, I got lazy in my commits (partial commits are possible if you update to the latest revision you want to push), and ended up starting to commit everything. So I killed the push and for the first time it failed to keep my later revisions.
I tried recover, but that was not able to find the parent commit. What worked for me was restoring the ...-backup.hg file (there was a ...-temp.hg file in strip-backup too).
The strange thing (which is why I'm answering this) is that it only gave me a warning about the parent not being there (I have no idea why)...
warning: ignoring unknown working parent d5663567bc4b!
adding changesets
adding manifests
adding file changes
added 21 changesets with 1255 changes to 941 files
(run 'hg update' to get a working copy)
BTW, I'm running Mercurial version 2.0

Fixing a failed integrity check in Mercurial?

I just did hg pull on a repository and brought in some changesets. It said to run hg update, so I did. Unfortunately, when I did that, it failed with the following error message:
abort: integrity check failed on 00manifest.i:173!
When I run hg verify, it tells me there are a number of issues with things not in the manifest (with some slight path obscuring):
>hg verify
checking changesets
checking manifests
crosschecking files in changesets and manifests
somewhere1/file1.aspx#172: in changeset but not in manifest
somewhere2/file1.pdf#170: in changeset but not in manifest checking files
file3.csproj#172: ee005cae8058 not in manifests
somewhere2/file1.pdf#171: 00371c8b9d95 not in manifests
somewhere3/file1.ascx#170: 5c921d9bf620 not in manifests
somewhere4/file1.ascx#172: 23acbd0efd3a not in manifests
somewhere5/file1.aspx#170: ce48ed795067 not in manifests
somewhere5/file2.aspx#171: 15d13df4206f not in manifests
1328 files, 174 changesets, 3182 total revisions
8 integrity errors encountered!
(first damaged changeset appears to be 170)
The source repository passes hg verify just fine.
Is there any way to recover from an integrity check failure or do I need to re-clone the repository completely from the source (not a huge issue in this case)? What could I have done to cause this, so I don't do it again?
Well, since the first damaged changeset is 170, you could clone your local repository to 169 and then pull from the source. That means only pulling 5 changesets.
hg clone -r 169 damagedrepo fixedrepo
cd fixedreop
hg verify
And then:
hg pull originalsource
As for manual recovery of repository corruption, this page expounds on that better than I can. See section 4:
I have found corruption once in a while before, and although the above
documentation says it is usually from user error, my instances were on
removable USB drives with empty working directories. Sometimes things
just don't get written correctly or are interfered with somehow: it's
not always user error. But I always have multiple copies I can reclone
from so I've been able to get away with basic fixing.
If the simple fix of a partial local clone and pulling from the server doesn't fix it, you're down to 2 options after backing up your changes (if any) to a bundle or patches:
Manually hacking at Mercurial's files.
Doing a new full clone from the server. Usually the easier and faster of the two.
Beware: This method will change all hashes.
Actually there is another way to recover the repository when it is corrupted like this -
You can do a complete rebuild of the repository by using the convert extension. See Section 4.5 on https://www.mercurial-scm.org/wiki/RepositoryCorruption#Recovery_using_convert_extension
First enable the convert extension by adding the following to your ~/.hgrc file
[extensions]
convert=
Then convert the bad repo to create a fixed repo:
$ hg convert --config convert.hg.ignoreerrors=True REPO REPOFIX
This worked for me when I had the experience of suddenly finding that there were missing files in the manifests - "error 255".
Try remove your file 00manifest.i from repo and next use hg remove 00manifest.i and hg commit commands. Worked for me.
What we ended up doing was making a new copy of our 'central' repository, deleting the .hg folder in this copy, creating a new repository there (hg init), and then working with this as the central repository.
Be aware however this is only an appropriate solution if you don't need your changeset history other than as a reference (which we don't). You can still use your old central repository for this purpose.

How do you delete a commit in Mercurial?

I want to completely delete a Mercurial commit as if it was never entered in the repository and move back to my prior commit.
Is this possible?
If it was your last commit and you haven't pushed it anywhere, you can do that with rollback. Otherwise, no. Not really. Time to change your passwords.
Edit: It has been pointed out that you can clone from an older revision and merge in the changes you want to keep. That's also true, unless you have pushed it to a repo you don't control. Once you push, your data is very likely to be very hard to get back.
You can try to remove mq info about your commit.
For this you need to go File->Settings->Extensions.
There check mq and restart gui.
After that just right click on unneeded commit and
ModifyHistory->Strip
To edit the history I would use the Histedit Extension extension.
hg histedit 45:c3a3a271d11c
However keep in mind this only makes sense in a situation where you have not yet pushed the commits to the public repository, you own the public repository and/or you can account for all the clones out there. If you receive the following error:
abort: can't rebase immutable changeset 43ab8134e7af
It means that Mecurial thinks this is a public changeset (see phases) that has already been pushed - you can force it to be a draft again doing:
hg phase -f -d 45:c3a3a271d11c
I encounter this fairly often. I make a commit and then pull to push. But then there is something incoming that makes my newly made commit unnecessary. A plain hg rollback isn't enough because it only undoes the pull...
This is the thing to do:
hg strip <rev>
Things are painless when you don't push your changesets anywhere.
If it's more than one commit and/or you already pushed it somewhere else, you can clone your repository and specify the last changeset that should be cloned.
See my answer here how to do this:
Mercurial: Fix a borked history
If you only committed locally and didn't push, you can just create a clone locally (as described in my link) and you're done.
If you already pushed to some remote repository, you would have to replace that with your clone.
Of course it depends if you are able (or allowed) to do this.
You can use "hg backout" to do a reverse merge basically. All options are discussed in the freely available book "Mercurial: The Definitive Guide":
http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html
If using tortoise you can use modify history > strip...
Yes. Unless I am mistaken, as of v2.3 (rel. 2012/08/01) you can use the HisteditExtension with a drop command to drop a commit, along with strip or backout to remove changes.
A simple Google search on the feature: https://www.google.com/webhp#q=histedit+drop
In 2022 I do use evolve extension. It is one of the best extensions for this purpose.
To prune unwanted changeset, if you for example did a quick hack to get the code working:
$ echo 'debug hack' >> file1.c
$ hg commit -m 'debug hack'
Now you have a proper patch you can do hg prune .:
$ hg prune .
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
working directory is now at 2a39221aaebb
1 changesets pruned
If you push the change to the remote repository you will find only obsolescence markers:
$ hg push
searching for changes
no changes found
remote: 1 new obsolescence markers
To check the changes to your local repo you can pull from the remote one:
$ hg pull
pulling from ssh://userid#server/repo
searching for changes
no changes found

How to resolve merging conflicts in Mercurial (v1.0.2)?

I have a merging conflict, using Mercurial 1.0.2:
merging test.h
warning: conflicts during merge.
merging test.h failed!
6 files updated, 0 files merged, 0 files removed, 1 files unresolved
There are unresolved merges, you can redo the full merge using:
hg update -C 19
hg merge 18
I can't figure out how to resolve this. Google search results instruct to use:
hg resolve
but for some reason my Mercurial (v1.0.2) doesn't have a resolve command:
hg: unknown command 'resolve'
How can I resolve this conflict?
To highlight an answer in a comment for Hg 1.1+:
For Hg 1.1+ fix the file by hand and then do
hg resolve -m test.h
to mark the file as merged.
Valid for hg < v1.1 only
There is no need to call any hg commands. Unlike svn, Mercurial does not track conflicted files. If you call hg status, you'll see that the file is simply marked as modified.
Just fix the file by hand and commit.
Tracking conflicts was introduced in Mercurial 1.1, which is a newer version that you are using (you should really upgrade, Mercurial 1.1. was released in December 2008).
In that version you gained the resolve command which works similarly to svn resolve.
As I remember it, Mercurial would leave merge markers (the <<<< and >>>> lines) in your file when there is a conflict, unless you have configured a merge tool. This also applies to newer versions -- I have no merge tool configured and get the merge markers when conflicts occur. I can then manually fix the file and mark it resolved with hg resolve.