Mercurial merge conflict on adjacent lines - mercurial

I found following case.
$ hg init
$ echo '
> line 1
> line 2
> ' > file.txt
$ hg add file.txt
$ hg commit -m 'added'
$ echo '
> line 11
> line 2
> ' > file.txt
$ hg commit -m 'changed line 1'
$ hg update 0
$ echo '
> line 1
> line 21
> ' > file.txt
$ hg commit -m 'changed line 2'
$ hg merge 1
The result:
merging file.txt failed!
hg diff file.txt
diff -r bc62305d407b file.txt
--- a/file.txt Fri Jun 17 22:53:22 2011 +0300
+++ b/file.txt Fri Jun 17 22:53:46 2011 +0300
## -1,4 +1,9 ##
+<<<<<<< local
line 1
line 21
+=======
+line 11
+line 2
+>>>>>>> other
If we try the above scenario, but with 3 lines and changes are on 1 and 2 line, the merge will succeed.
So, my question why this is happenning? Is this is a issue with the merge algorithm or something else?

Mercurial just cannot merge automatically because there's a conflict a human has to resolve. How should Mercurial know if the merged version should contain
line 1
line 21
or
line 11
line 2
Mercurial does not consider one side of the merge as an authority which could take precedence. The markers in file.txt are Mercurial's hints for you where your hands are needed.
However, you can avoid such in-file markers by configuring an interactive merge tool to be used on conflicts. Also have a look at this related question.

Related

Hg command to get the file content without switching branch

In HG, is there any command such that i can get the file content of the file from another branch without switching/checkout to the particular branch?
Similar to the other answer, you can use the cat command but in a slightly different way:
hg cat --rev=11204 path/to/file
This will pick the file from revision #11204 which can be any branch.
You may want to add the --output switch lets you use whatever filename and/or location you want:
hg cat --output=C:/new/path/to/file/filename#11204.ext --rev=11204 path/to/file
If you are using TortoiseHG, you can use the "save at revision" command to do this.
Steps:
Run Tortoise Workbench
Find the changeset in history which has the file revision you want (could be in any branch)
Say its changeset #abcd1234
Right click on the specific file in the file list for that changeset
Select "Save at revision..." and tell it where to put the file.
The file would typically be named filename#abcd1234.ext so that you don't mix it up with the current version.
Use the cat subcommand with the revision number of the commit you're looking for.
Here's an example. I create two branches with the contents of the file file indicating which branch it's on. Then I use cat to examine the contents on both branches
% hg init foo
% cd foo
% echo "default branch" > file
% hg add file
% hg ci -m 'default' file
% echo "default 2nd rev" > file
% hg ci -m 'default 2nd rev' file
% hg glog
# changeset: 1:305b2b5ccbd9
| tag: tip
| user: dj
| date: Mon Sep 17 14:11:20 2018 -0400
| summary: default 2nd rev
|
o changeset: 0:6d22c68d8abc
user: dj
date: Mon Sep 17 14:10:56 2018 -0400
summary: default
% hg co -r 0
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
% echo "new branch" > file
% hg branch 'new branch'
marked working directory as branch new branch
(branches are permanent and global, did you want a bookmark?)
% hg ci -m 'new branch'
% hg glog
# changeset: 2:4c8d2181526c
| branch: new branch
| tag: tip
| parent: 0:6d22c68d8abc
| user: dj
| date: Mon Sep 17 14:12:30 2018 -0400
| summary: new branch
|
| o changeset: 1:305b2b5ccbd9
|/ user: dj
| date: Mon Sep 17 14:11:20 2018 -0400
| summary: default 2nd rev
|
o changeset: 0:6d22c68d8abc
user: dj
date: Mon Sep 17 14:10:56 2018 -0400
summary: default
% hg branches
new branch 2:4c8d2181526c
default 1:305b2b5ccbd9
% hg cat -r 2 file
new branch
% hg cat -r 1 file
default 2nd rev

hg shelve created a commit, I don't understand

I'm a bit confused by hg shelve because the documentation is rather sparse. Somehow I got a commit in my log of the form:
changeset: 29:ad47ed1ca915
parent: 27:afca280f2884
user: shelve#localhost
date: Wed Jun 08 15:30:36 2016 -0600
summary: changes to: ...
I'm confused as to where this came from. It was my understanding that shelve was just stuffing things on the local machine and that they wouldn't get in the history. Am I misunderstanding that?
Here's my hg command history:
hg status
hg shelve list
hg shelve --list
hg unshelve
hg unshelve
hg resolve
hg resolve -all
hg resolve --all
hg resolve --all
hg clone a/ b
# By this point we have the commit (since 28 is after 27)
hg update -r 28
EDIT:
Ok, so the problem seems to be a partial unshelve. However, because I pull the changesets else where now I'm stuck with the changesets and am not sure what to do :(
EDIT2: Here's an example of how to cause this problem:
~ $ cd tmp
~/tmp $ mkdir shelve shelve/a
~/tmp $ cd shelve/a
~/tmp/shelve/a $ hg init
~/tmp/shelve/a $ echo a > a
~/tmp/shelve/a $ hg add a
~/tmp/shelve/a $ hg commit -m "a as a"
~/tmp/shelve/a $ cd ..
~/tmp/shelve $ hg clone a b
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
~/tmp/shelve $ cd b
~/tmp/shelve/b $ echo aa > a
~/tmp/shelve/b $ hg commit -m "a as aa"
~/tmp/shelve/b $ cd ../a
~/tmp/shelve/a $ echo aaa > a
~/tmp/shelve/a $ hg shelve
shelved as default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
~/tmp/shelve/a $ hg pull -u ../b
pulling from ../b
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
~/tmp/shelve/a $ hg unshelve
unshelving change 'default'
rebasing shelved changes
rebasing 2:6696488053d1 "changes to: a as a" (tip)
merging a
3 files to edit
was merge successful (yn)? n
merging a failed!
unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
~/tmp/shelve/a $ hg heads
changeset: 2:6696488053d1
tag: tip
parent: 0:845abf4a2513
user: shelve#localhost
date: Thu Jun 16 19:44:05 2016 -0600
summary: changes to: a as a
changeset: 1:e1f75f582f85
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 19:44:05 2016 -0600
summary: a as aa
Here's my solution. Also shows a bit more of the problem. The problem comes if you do an hg pull with an unresolved unshelve.
~ $ cd tmp
~/tmp $ cd shelve/a
~/tmp/shelve/a $ hg resolve a
merging a
3 files to edit
continue: hg unshelve --continue
~/tmp/shelve/a $ cd ../b
~/tmp/shelve/b $ echo Cause failure
Cause failure
~/tmp/shelve/b $ hg pull ../a
pulling from ../a
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
~/tmp/shelve/b $ hg heads
changeset: 2:6696488053d1
tag: tip
parent: 0:845abf4a2513
user: shelve#localhost
date: Thu Jun 16 19:44:05 2016 -0600
summary: changes to: a as a
changeset: 1:e1f75f582f85
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 19:44:05 2016 -0600
summary: a as aa
~/tmp/shelve/b $ cd ../a
~/tmp/shelve/a $ hg unshelve --continue
rebasing 2:6696488053d1 "changes to: a as a" (tip)
unshelve of 'default' complete
~/tmp/shelve/a $ hg commit -m "a as aaa"
~/tmp/shelve/a $ cd ../b
~/tmp/shelve/b $ hg pull
pulling from /home/crazycasta/tmp/shelve/a
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)
~/tmp/shelve/b $ echo Problem
Problem
~/tmp/shelve/b $ hg heads
changeset: 3:a804c9f51cd6
tag: tip
parent: 1:e1f75f582f85
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 20:02:43 2016 -0600
summary: a as aaa
changeset: 2:6696488053d1
parent: 0:845abf4a2513
user: shelve#localhost
date: Thu Jun 16 19:44:05 2016 -0600
summary: changes to: a as a
~/tmp/shelve/b $ echo Solution
Solution
~/tmp/shelve/b $ hg strip -r 2
saved backup bundle to /home/crazycasta/tmp/shelve/b/.hg/strip-backup/6696488053d1-313495de-backup.hg
~/tmp/shelve/b $ hg heads
changeset: 2:a804c9f51cd6
tag: tip
user: Alex Orange <crazycasta#gmail.com>
date: Thu Jun 16 20:02:43 2016 -0600
summary: a as aaa

How to display outgoing diff without merges?

When using mercurial, when working on a large change, I will do several commits (as safe points, or share my progress with coworkers).
Whe I am done, I want to push my changes into the main repository. Before I do that, though, I will want to do a "hg pull -u && hg merge"to get changes that occured since my last pull, and review my changes.
Because I have several changesets, running hg diff on each of those is not a good solution.
I tried running hg diff -c"outgoing() and not merge()" to only show the diff for my outgoing changesets (without merge ones, as this tends to only add noise which I want to avoid).
However, it is still not ok for me, as mercurial seems to skip some information, and I do not understand on what basis. Please refer to the scenario below:
full scenario:
# clean working directory
rm -fr base clone
#prepare reference repo
mkdir base; cd base
hg init
touch 1.txt
echo " 1\n2" >>1.txt
hg add 1.txt
touch 2.txt
hg add 2.txt
hg commit -m"initial commit"
cd ..
hg clone base clone
cd base
#update ref repo.
echo "foo" >> 1.txt
hg commit -m"update file on remote repository"
#make changes locally
cd ../clone
echo "foo" >> 2.txt
hg commit -m "update initial file"
#now we are ready to push
hg pull -u && hg merge
hg commit -m"merge"
#actually...
sed -i -e 's/foo/bar/' 2.txt
hg commit -m"changed my mind"
hg out
changeset: 1:fce14ac089b2
date: Thu Nov 14 11:17:08 2013 +0100
summary: update initial file
changeset: 3:1967c50242c0
parent: 1:fce14ac089b2
parent: 2:2cdaf75afc6d
date: Thu Nov 14 11:17:10 2013 +0100
summary: merge
changeset: 4:120a0b8a0ede
tag: tip
date: Thu Nov 14 11:18:54 2013 +0100
summary: changed my mind
#try to display my changes
hg diff -c"outgoing() and not merge()"
--- a/2.txt Thu Nov 14 11:17:10 2013 +0100
+++ b/2.txt Thu Nov 14 11:18:54 2013 +0100
## -1,1 +1,1 ##
-foo
+bar
#only one change here!
#but
hg log -r"outgoing() and not merge()"
changeset: 1:fce14ac089b2
date: Thu Nov 14 11:17:08 2013 +0100
summary: update initial file
changeset: 4:120a0b8a0ede
tag: tip
date: Thu Nov 14 11:18:54 2013 +0100
summary: changed my mind
#is ok
So, could anyone please explain to me why mercurial skips changeset fce14ac089b2 entirely? What I expect is a consolidated output, i.e something like:
--- a/2.txt
+++ b/2.txt
## -1,1 +1,1 ##
+bar
Thanks a lot in advance.
I think the problem is a misunderstanding of what hg diff -c aka hg diff --change does. It takes a single revision id and shows you the change made by that one revision relative to its left parent.
You're calling:
hg diff -c"outgoing() and not merge()"
which yields multiple revisions (it's a revision set), but only one of them is being used. You're essentially seeing the output of:
hg diff --change 120a0b8a0ede
If what you're trying to do is see all of your outgoing changes lumped together in one diff you don't want --change/-c.
If you think about it the revset outgoing() could contain many changeset from many branches so smooshing them all into one diff isn't necessarily possible at all.
If the view you're trying to get is "how does the most recent head on branch default locally compare to the most recent head on default remotely" you need to know the node id of the most recent head on default, and then locally you'd just run:
hg diff node_id_of_most_recent_head_on_default_at_remote_site
This isn't guaranteed, as I expect that there's some way to have a change graph where the last public ancestor isn't the change-set you're after, but...
> hg diff -r "last(ancestors(.) and public())"
diff -r 5579be654db4 2.txt
--- a/2.txt Sat Nov 16 11:03:06 2013 +0000
+++ b/2.txt Sat Nov 16 11:29:34 2013 +0000
## -0,0 +1,1 ##
+bar

Mercurial, how to tag old version of files

I forgot to tag and older version of my files with a release tag. The older version is at r13, latest is about r65. I cloned the latest repository to a new directory, did an "hg update -r13" to get the older code I wanted to tag, then did the tag command, but got the message:
abort: not at a branch head (use -f to force)
Is it safe to use the -f option in this situation?
I guess you can still do the tagging right in the repo without updating yourself to a particular revision.
hg tag -r 13 tagname
See the details at Mercurial wiki.
I tried testing it :
temp $ hg init .
temp $ touch a.txt
temp $ hg add a.txt
temp $ hg commit -m "added a"
temp $ hg status
temp $ echo "sdwwdd" >> a.txt
temp $ hg commit -m "modified a"
temp $ echo "\neddwedd" >> a.txt
temp $ hg commit -m "modified a again"
temp $ hg log
changeset: 2:ef40a402fdab
tag: tip
user: "xxxx"
date: Fri Dec 23 16:51:48 2011 -0800
summary: modified a again
changeset: 1:d630dc3e2e3a
user: "xxxx"
date: Fri Dec 23 16:51:31 2011 -0800
summary: modified a
changeset: 0:7c9917f24515
user: "xxxx"
date: Fri Dec 23 16:51:04 2011 -0800
summary: added a
Output:
temp $ hg tag -r 1 a.txt a_1
temp $ hg tags
tip 3:e3157256098f
a_1 1:d630dc3e2e3a
a.txt 1:d630dc3e2e3a
temp $ hg tag -r 1 all_1
temp $ hg tags
tip 4:a643971911d8
all_1 1:d630dc3e2e3a
a_1 1:d630dc3e2e3a
a.txt 1:d630dc3e2e3a

How can I mark a file as descended from 2 other files in Mercurial?

I had 2 Python similar scripts, that I've since merged into one (and now takes some parameters to differ the behaviour appropriately). Both of the previous files are in the tip of my Mercurial repository. How can I indicate that the new file, is a combination of the 2 older files that I intend to remove?
Also note, that 1 file has been chosen in favor of the other, and some code moved across, so if it's not possible to create a version controlled file with a new name, then assimilating one file's history into the other will suffice.
It's not a perfect solution, and it might be too late to do it this time, but I think hg rename would get you where you want to go. Here's a sequence:
ry4an#hail [~/hg] % mkdir test
ry4an#hail [~/hg] % cd test/
ry4an#hail [~/hg/test] % hg init
ry4an#hail [~/hg/test] % echo stuff > file1
ry4an#hail [~/hg/test] % echo different > file2
ry4an#hail [~/hg/test] % hg commit --addremove -m 'adding both separately'
adding file1
adding file2
ry4an#hail [~/hg/test] % hg rename --force file1 file2
ry4an#hail [~/hg/test] % hg commit -m 'overwrote 2 with 1'
ry4an#hail [~/hg/test] % hg grep --follow different file2
file2:0:different
ry4an#hail [~/hg/test] % hg grep --follow stuff file2
file2:1:stuff
Notice that the file 'grep' find that 'stuff' was in file2 revision 1 and 'different' was in file two revision 0, so both histories are now in file2.
What follows is an example of a merge between two unrelated files "a" and "b".
Please note that I'm abusing a list format because I can't figure out how to use this system. Lines that appear to be headers but start as "summary:" are actually output from hg and happen to be the last line before a blank line. All other headers are my own comments explaining a command/sequence and its output. Commands appear on line that have 'timeless-mbp:...$'. All other lines are output.
Setup
timeless-mbp:~ timeless$ cd /tmp
timeless-mbp:tmp timeless$ rm -rf q
timeless-mbp:tmp timeless$ hg init q
timeless-mbp:tmp timeless$ cd q
Define my username
timeless-mbp:q timeless$ echo '[ui]' > .hg/hgrc
timeless-mbp:q timeless$ echo 'username = timeless' >> .hg/hgrc
First create, add and commit file a
timeless-mbp:q timeless$ echo a > a
timeless-mbp:q timeless$ hg commit -Am a
adding a
Start at a new scratch revision (null)
timeless-mbp:q timeless$ hg up -r null
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
Create, add and commit file b
timeless-mbp:q timeless$ echo b > b
timeless-mbp:q timeless$ hg commit -Am b
adding b
created new head
Switch back to our first file, this is just to create an interleaved version history
timeless-mbp:q timeless$ hg up -r 0
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
Rename a to file because we want to merge it with b under the name "file"
timeless-mbp:q timeless$ hg mv a file
timeless-mbp:q timeless$ hg commit -m 'rename a to file'
Switch back to our second file, this is just to create an interleaved version history
timeless-mbp:q timeless$ hg up -r 1
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
Rename b to file because we want to merge it with a under the name "file"
timeless-mbp:q timeless$ hg mv b file
timeless-mbp:q timeless$ hg commit -m 'rename b to file'
I'm forcing a merge using internal because I don't want a merge tool to pop up, there are other merge tools you could use (e.g. on OS X with modern versions of Mercurial, it tends to pop up FileMerge.app, but that's hard to show in a log).
timeless-mbp:q timeless$ hg --config ui.merge=internal:local merge 2
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
Replace the content with what I want
timeless-mbp:q timeless$ hg cat -r 2 file > file
timeless-mbp:q timeless$ hg cat -r 3 file >> file
Verify that it now has the content I want
timeless-mbp:q timeless$ cat file
a
b
Commit the "merged" file
timeless-mbp:q timeless$ hg commit -m merging
Review the repository history
timeless-mbp:q timeless$ hg log
changeset: 4:d9d3d23ec1cc
tag: tip
parent: 3:01c6a61cbe04
parent: 2:3de70df713a7
user: timeless
date: Wed Jun 02 16:10:08 2010 +0300
summary: merging
changeset: 3:01c6a61cbe04
parent: 1:e6b8058965b4
user: timeless
date: Wed Jun 02 16:09:43 2010 +0300
summary: rename b to file
changeset: 2:3de70df713a7
parent: 0:635f50240100
user: timeless
date: Wed Jun 02 16:09:30 2010 +0300
summary: rename a to file
changeset: 1:e6b8058965b4
parent: -1:000000000000
user: timeless
date: Wed Jun 02 16:09:17 2010 +0300
summary: b
changeset: 0:635f50240100
user: timeless
date: Wed Jun 02 16:09:01 2010 +0300
summary: a
Check annotate output
timeless-mbp:q timeless$ hg ann -f -c file
635f50240100 a: a
e6b8058965b4 b: b