Mercurial uncommited changes merged when changing branches - mercurial

I've accidently switched branches while having uncommitted changes. It seems that mercurial has automatically merged my changes, but there are conflicts left behind.
How can I go back to having my named branch checked out and commit my changes there?

It seems that mercurial has automatically merged my changes
In seems only for you (and your Mercurial), because for this toy-repo
# 2[tip] e173e81c9fff 2016-07-08 10:09 +0500 lazybadger
| Creating branch
|
o 1 befd1e011923 2016-07-08 10:06 +0500 lazybadger
| Edit
|
o 0 45f15df3f7c9 2016-07-08 10:05 +0500 lazybadger
Start
and dirty working dir at rev. 1
>hg id -nib
befd1e011923+ 1+ default
>hg st
M 1.txt
update to tip doesn't change content of file in working directory
>hg up Feature
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(note "0 files updated, 0 files merged") and working directory is still dirty
>hg id -nib
e173e81c9fff+ 2+ Feature
>hg st
M 1.txt
PS - you can just disable update to another changeset if your working directory isn't clean: use -c option as mandatory for all hg up (create alias)

Related

Why don't tags in a separate Mercurial branch work?

I'm setting up a Mercurial repository to track third-party code, roughly following the vendor-default branch scheme described in Rudi's answer to this question. In order to quickly retrieve a particular version, I create tags for each vendor and default version.
I initialize the repo by committing an empty .hgtags to establish the default branch, then I hg branch vendor and import the first version. The process to add a new version looks like this:
hg up -C vendor
... load new version ...
hg commit -A -m "Adding version x.y.x"
hg tag vendor-x.y.z
hg up -C default
hg merge vendor
hg commit -m "Merging version x.y.z"
hg tag x.y.z
During the merge I always keep the local copy of .hgtags, so the result is that the vendor branch has .hgtags containing all the vendor-x.y.z tags while the default branch .hgtags has only the x.y.z tags.
It's my understanding that Mercurial considers .hgtags from all heads when working with tags. Yet when I run hg tags the result contains only tip and the x.y.z tags. This is the same regardless of which branch my working directory is updated to; it's always the tags from the default branch .hgtags file.
I can update to the vendor-x.y.z tags, so Mercurial does see their existence, but the update appears to give me code from the vendor branch tip. The x.y.z tags work fine.
I've worked mainly with Git and SVN/CVS in the past, so I assume that this is a problem of understanding, not a technical issue. I did try it, just in case, on two versions of Mercurial (2.0.2 and 2.3.2) and got the same results.
I'm not in front of my Mercurial system to verify, but I think the issue is Mercurial only considers .hgtags from topological heads, not branch heads. Example:
[1]---[2]---[5]---[6] Default
\ /
[3]---[4] Vendor
[6] is a topological head, [4] and [6] are branch heads. The solution is to keep all changes to .hgtags on a merge.
Edit
Here's my test. Directly after the merge I accepted the local .hgtags and hg tags only displays the tag on default. I can't update to the vendor tag, which differs from what you are seeing. I'm using Mercurial 2.3.1. After creating another changeset on vendor and making a second topological head, the missing tag reappears.
hg init test
cd test
echo >a
hg ci -Am 1
hg branch vendor
echo >b
hg ci -Am 2
hg tag v1
hg update default
hg tag d1
hg merge vendor --tool internal:local
hg ci -m Merge
#REM This only shows 'tip' and 'd1'
hg tags
hg update vendor
hg tags
hg update d1
#REM This fails to update.
hg update v1
# Add another topological head by committing to vendor
hg update vendor
echo >c
hg ci -Am 3
# Now all tags are visible and work.
hg tags
hg update v1
hg update d1
And the output:
C:\>hg init test
C:\>cd test
C:\test>echo 1>a
C:\test>hg ci -Am 1
adding a
C:\test>hg branch vendor
marked working directory as branch vendor
(branches are permanent and global, did you want a bookmark?)
C:\test>echo 1>b
C:\test>hg ci -Am 2
adding b
C:\test>hg tag v1
C:\test>hg update default
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
C:\test>hg tag d1
C:\test>hg merge vendor --tool internal:local
1 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
C:\test>hg ci -m Merge
C:\test>hg tags
tip 4:80759c41b3cc
d1 0:17b05ed457d1
C:\test>hg update vendor
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\test>hg tags
tip 4:80759c41b3cc
d1 0:17b05ed457d1
C:\test>hg update d1
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
C:\test>hg update v1
abort: unknown revision 'v1'!
C:\test>hg update vendor
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
C:\test>echo 1>c
C:\test>hg ci -Am 3
adding c
C:\test>hg tags
tip 5:a2c0fe73a9f1
v1 1:3168d0f4e5e5
d1 0:17b05ed457d1
C:\test>hg update v1
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
C:\test>hg update d1
0 files updated, 0 files merged, 1 files removed, 0 files unresolved

How do I diff one branch with my default branch

I switched to a branch on my local repo and noticed it gave me message showing x files updated. This surprised me as I didn't know there were any differences on that branch. How do I compare that branch with the default branch to see what has changed?
Use hg diff -r BRANCH1:BRANCH2, where BRANCH1 and BRANCH2 are the names of the branches. This will show you the differences between the heads of the two branches.
You got the message about "x files updated" because there were files changed on the original branch, not necessarily because there were files changed on the other branch. Mercurial shows you the union of the sets of changed files from both branches.
To just list the files with differences, add the --stat option:
hg diff --stat -r BRANCH1:BRANCH2
This gives output like this:
mypath/file1.cpp | 1 -
mypath/file2.cpp | 143 ++++++++++
mypath/file3.cpp | 18 +-
3 files changed, 160 insertions(+), 2 deletions(-)
Or to clean up the output a bit, pipe it through sed to remove everything after the pipe symbols:
hg diff --stat -r BRANCH1:BRANCH2 | sed "s/|.*$//g"
This gives you just a list of the changed files and the summary line at the end:
mypath/file1.cpp
mypath/file2.cpp
mypath/file3.cpp
3 files changed, 160 insertions(+), 2 deletions(-)
To view a diff of branch otherbranch with the current branch:
hg diff -r otherbranch

Mercurial deleted a untracked file

In our repository we have initial version of database (binary file).
I have executed hg pull and I saw that someone committed another version of this file.
As I won't to loose my changes in dev db, I did make a copy of it (copy file.db my_file.db) in same directory.
When I runned hg up, mercurial overwrited file.db with new version and deleted my_file.db!
I'm on windows 7 x64, and tried various software that recover deleted files, but with no success.
How can I get back my version of file.db or recover my_file.db? I didn't commit it.
I really don't think mercurial deleted your untracked file. Here's the sequence you've described as I understand it:
ry4an#four:~$ mkdir zote
ry4an#four:~$ cd zote
ry4an#four:~/zote$ hg init orig
ry4an#four:~/zote$ echo text > orig/file.db
ry4an#four:~/zote$ hg -R orig commit -A -m 'initial'
adding file.db
ry4an#four:~/zote$ hg clone orig clone
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
ry4an#four:~/zote$ mv clone/file.db clone/my_file.db
ry4an#four:~/zote$ echo more text >> orig/file.db
ry4an#four:~/zote$ hg -R orig commit -m 'new line'
ry4an#four:~/zote$ hg -R clone pull
pulling from /home/ry4an/zote/orig
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
ry4an#four:~/zote$ hg -R clone update
remote changed file.db which local deleted
use (c)hanged version or leave (d)eleted? c
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
ry4an#four:~/zote$ ls clone/
file.db my_file.db
ry4an#four:~/zote$ cat clone/my_file.db
text
ry4an#four:~/zote$ hg -R clone status
? my_file.db
You can see that afterward my_file.db is still there. Even with --clean as Mikezx6r mentiones the file is still there:
pulling from /home/ry4an/zote/orig
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
ry4an#four:~/zote/clone$ hg update --clean
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
ry4an#four:~/zote/clone$ ls -l
total 8
-rw-r--r-- 1 ry4an ry4an 15 2011-02-08 14:31 file.db
-rw-r--r-- 1 ry4an ry4an 5 2011-02-08 14:28 my_file.db
ry4an#four:~/zote/clone$ hg stat
? my_file.db
ry4an#four:~/zote/clone$
It's not what you want to hear, but it's much more likely you accidentally botched the 'mv' and only thought you created the copy or somehow externally deleted it. Or your antivirus app saw a pattern it didn't like a refused to create it, or some other horrible, accidental thing.
It's also not helpful now, but this is a great example of why you should commit early and often, and especially before updating -- it's just too easy to make mistakes, but once something in in the repo there's nothing you can do to accidentally remove it.

Hg: How to walk through changsets incrementally?

I'm new to Hg. I have a feature that was working, but now isn't. I want to progressively revert changes until I get to a revision where it works. I'm not quite sure what the best way to do this is.
I tried cloning the repo to an old revision, and saw that it worked there. So... how now do I update to subsequent changes? In the cloned repo, the default and tip revision is the one that I cloned it to.
Do I need to apply patches? Shelve changes? I'm not really sure.
You should use the bisect command to quickly figure out when your feature stopped working. It works as follows:
You start by resetting the bisect state and by marking your current working directory parent revision as bad:
hg bisect --reset
hg bisect --bad
Now make a guess about when you think the feature was working. If you think it was working on June 1st, then you can do
hg update -d '<Jun 1'
The update command is what you use to update the working directory to match a given changeset. See hg help dates for the list of date formats. You should now test this revision and if the feature works here, then you mark it as good:
hg bisect --good
If the feature is not working in this changeset then mark it as bad and update even further into the past:
hg bisect --bad
hg update -d '<May 1'
Repeat this until you find a good revision. When you have found a good revision, Mercurial can begin helping you: the changesets between the good and the bad changesets must contain the bug. Mercurial will help you by keeping track of the list of candidate changesets and help you narrow the list down to a single changeset. It does this by updating you to a changeset roughly in the middle of the candidates and asking you to test this changeset.
After testing, you mark the changeset as good or bad. If you mark it as good, then you know the bug lies further in the future, and if you mark it as bad, then the bug lies further in the past. In either case, you cut away about half of the candidates in each step! This means that you only need 10 steps to test 1024 candidates -- this is the power of logarithms :-) Mercurial will keep track of the candidates and update you to a new spot after each test.
A full session could look like this (I'm just saying good/bad by random here):
% hg bisect --reset
% hg bisect --bad
% hg update -r -100
61 files updated, 0 files merged, 9 files removed, 0 files unresolved
% hg bisect --good
Testing changeset 11414:0fa4474bdc2f (99 changesets remaining, ~6 tests)
46 files updated, 0 files merged, 0 files removed, 0 files unresolved
% hg bisect --good
Testing changeset 11439:778377be3662 (50 changesets remaining, ~5 tests)
17 files updated, 0 files merged, 0 files removed, 0 files unresolved
% hg bisect --bad
Testing changeset 11428:4d03c3680400 (25 changesets remaining, ~4 tests)
6 files updated, 0 files merged, 0 files removed, 0 files unresolved
% hg bisect --bad
Testing changeset 11420:a99ef3711890 (13 changesets remaining, ~3 tests)
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
% hg bisect --bad
Testing changeset 11417:6f1d1ed3e19a (6 changesets remaining, ~2 tests)
4 files updated, 0 files merged, 0 files removed, 0 files unresolved
% hg bisect --good
Testing changeset 11418:67bb9d78f05e (3 changesets remaining, ~1 tests)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
% hg bisect --bad
The first bad revision is:
changeset: 11418:67bb9d78f05e
user: Matt Mackall
date: Mon Jun 21 13:25:42 2010 -0500
summary: merge: sort arguments to stabilize the ancestor search
I would iterate through the remaining change-sets using
hg pull -r <revision> [<original repo>]
Some docs here.
To find the revision exactly at which the feature was missing you can try hg bisect.
you can find it here.
tip the latest revision in the repo, default the name of branch which is by default in the repo when you created it. you can add the remaining changesets(changes) by pulling them.
hg help pull

Mercurial undo merge that has more commits following it?

Have a scenario where we un-intentionally merged a named branch (ABC) into our default branch.
hg rollback is not an option because there have been a couple commits since.
Is there a way to undo this?
You're going to need the Mq extension. If you don't have it turned on, do so by adding this to your Mercurial.ini or .hgrc file.
[extensions]
hgext.mq=
If you're not familiar with it, the Mq extension let's you manipulate history. The good news is, this will allow us to fix your repo. The bad news is that anyone who has a clone of the messed up repo will have to clone it again, because we'll be changing history.
First, go make another clone of your repo to work in, so we don't mess anything up.
Now, find the revision id of the merge changeset (that merged default and your named branch). Write it down. We'll refer to it as changesetM. Now find the revision id of the next changeset. Write it down. We'll refer to it as changesetN.
Once you have those two revision ids, head over to your command prompt and cd into your repo. Then type out the following, replacing changeset[M|N] with the appropriate revision id.:
$ hg qimport -r changesetN:tip
# This will add all of your changes since the merge to the queue
$ hg qpop -a
# This pops them all out of your history.
$ hg strip changesetM
# This removes the merge changeset.
$ hg update -C default
# Make sure we're on the default branch
$ hg qpush -a
# Take the changesets in the queue and push them back onto your history.
$ hg qfinish -a
# Remove changesets from the queue and finalize them as normal changesets.
Essentially, you are rebasing the new changesets on top of the default branch, removing the merge changeset in the process. Once you're done, you'll need to push the changes to a new repository on the server, and have your colleagues clone fresh copies.
Lastly, if you have any other Mercurial questions, also check out kiln.stackexchange.com.
UPDATE
I forgot to mention: If someone has based changes on something that was only in the other branch, it is possible that hg qpush -a will fail. You'll see a foo.txt.rej and foo.txt.orig file laying around. Unfortunately, you'll have to fix this yourself. To fix it, open the original file, the .orig file, and the .rej file and choose the right changes to merge in, saving them in the original file. Once you've merged it in, use hg qrefresh to update that patch to the new, merged patch. From their, you should be able to run hg qpush -a again and continue. If you run into the same error again on another patch, just follow the same process.
If you haven't publish the repo publicly you can do this
hg clone -r (parent1 of bad merge) -r (parent2 of bad merge) old new
and delete the old repo.
I came across the following scenario today:
# changeset: 1728:5d703e1051d3
|\ parent: 1727:1a5f73b5edb4
| | parent: 1720:65ddd0bde225
| | user: nn
| | date: Wed Feb 27 10:35:00 2013 +0100
| | summary: Merge with SomeBranch
| |
| o changeset: 1727:1a5f73b5edb4
| | user: nn
| | date: Wed Feb 27 10:34:30 2013 +0100
| | summary: lorem ipsum
| |
[some more changesets]
| |
o | changeset: 1720:65ddd0bde225
| | branch: SomeBranch
| | user: nn
| | date: Wed Feb 27 07:44:46 2013 +0100
| | summary: lorem ipsum
Where SomeBranch should not have been merged into default. What we did to solve this, was to use the backout command with the parent option like so:
hg backout --rev=1728 --parent=1727
By this you don't undo the merge itself: Looking at a branch graph (either with graph log or in TortoiseHg) you'll still see SomeBranch going into default at r1728. The result of the merge is however undone, meaning that the changeset containing the backout (r1729 in my case) is identical to r1727.