From: Shawn O. Pearce <hidden> Date: 2016-08-11 19:45:27
Prior to 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae we deleted a
file from the working directory during a merge if the file existed
in the working directory before the merge started but was renamed
by the branch which is being merged in. This broke in 65ac63 as
git-merge-recursive did not actually update the working directory
on this uncontested rename case.
Signed-off-by: Shawn O. Pearce <redacted>
---
The same repository that spawned my 'Bug in merge-recursive in
virtual commit corner case' thread discovered this feature of
git-merge-recursive today.
I'm not sure this is the right way to fix the issue, but it does
appear to fix the problem and passes both the existing tests and
this new one.
merge-recursive.c | 2 +-
t/t6024-merge-rename2.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 1 deletions(-)
@@ -0,0 +1,97 @@+#!/bin/sh++test_description='Merge-recursive merging renames'+../test-lib.sh++test_expect_successsetup\+'+cat>A<<\EOF&&+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+ccccccccccccccccccccccccccccccccccccccccccccccccc+ddddddddddddddddddddddddddddddddddddddddddddddddd+eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee+fffffffffffffffffffffffffffffffffffffffffffffffff+ggggggggggggggggggggggggggggggggggggggggggggggggg+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh+iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii+jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj+kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk+lllllllllllllllllllllllllllllllllllllllllllllllll+mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm+nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn+ooooooooooooooooooooooooooooooooooooooooooooooooo+EOF++cat>M<<\EOF&&+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF+GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG+HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ+KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK+LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM+NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO+EOF++gitaddAM&&+gitcommit-m"initial has A and M"&&+gitbranchwhite&&+gitbranchred&&++gitcheckoutwhite&&+sed-e"/^g /s/.*/g : white changes a line/"<A>B&&+sed-e"/^G /s/.*/G : colored branch changes a line/"<M>N&&+rm-fAM&&+gitupdate-index--add--removeABMN&&+gitcommit-m"white renames A->B, M->N"&&++gitcheckoutred&&+echocreatedbyred>R&&+gitupdate-index--addR&&+gitcommit-m"red creates R"&&++gitcheckoutmaster'++# This test broke in 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae+test_expect_success'merge white into red (A->B,M->N)'\+'+gitcheckout-bred-whitered&&+gitmergewhite&&+gitwrite-tree>/dev/null||{+echo"BAD: merge did not complete"+return1+}++test-fB||{+echo"BAD: B does not exist in working directory"+return1+}+test-fN||{+echo"BAD: N does not exist in working directory"+return1+}+test-fR||{+echo"BAD: R does not exist in working directory"+return1+}++test-fA&&{+echo"BAD: A still exists in working directory"+return1+}+test-fM&&{+echo"BAD: M still exists in working directory"+return1+}+return0+'++test_done
@@ -873,7 +873,7 @@ static int process_renames(struct path_list *a_renames,structdiff_filespecsrc_other,dst_other;inttry_merge,stage=a_renames==renames1?3:2;-remove_file(1,ren1_src,1);+remove_file(1,ren1_src,0);
I _think_ that the "0" should be "!index_only".
Err, actually "index_only". Since that's no_wd. But yea, you are
right, I didn't consider the index_only mode of operation here.
-->-- corrected patch follows --<--
Remove uncontested renamed files during merge.
Prior to 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae we deleted a file
from the working directory during a merge if the file existed before
the merge started but was renamed by the branch being merged in.
This broke in 65ac63 as git-merge-recursive did not actually update
the working directory on an uncontested rename.
Signed-off-by: Shawn O. Pearce <redacted>
---
merge-recursive.c | 2 +-
t/t6024-merge-rename2.sh | 97 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 1 deletions(-)
@@ -0,0 +1,97 @@+#!/bin/sh++test_description='Merge-recursive merging renames'+../test-lib.sh++test_expect_successsetup\+'+cat>A<<\EOF&&+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+ccccccccccccccccccccccccccccccccccccccccccccccccc+ddddddddddddddddddddddddddddddddddddddddddddddddd+eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee+fffffffffffffffffffffffffffffffffffffffffffffffff+ggggggggggggggggggggggggggggggggggggggggggggggggg+hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh+iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii+jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj+kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk+lllllllllllllllllllllllllllllllllllllllllllllllll+mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm+nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn+ooooooooooooooooooooooooooooooooooooooooooooooooo+EOF++cat>M<<\EOF&&+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC+DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE+FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF+GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG+HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII+JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ+KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK+LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM+NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO+EOF++gitaddAM&&+gitcommit-m"initial has A and M"&&+gitbranchwhite&&+gitbranchred&&++gitcheckoutwhite&&+sed-e"/^g /s/.*/g : white changes a line/"<A>B&&+sed-e"/^G /s/.*/G : colored branch changes a line/"<M>N&&+rm-fAM&&+gitupdate-index--add--removeABMN&&+gitcommit-m"white renames A->B, M->N"&&++gitcheckoutred&&+echocreatedbyred>R&&+gitupdate-index--addR&&+gitcommit-m"red creates R"&&++gitcheckoutmaster'++# This test broke in 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae+test_expect_success'merge white into red (A->B,M->N)'\+'+gitcheckout-bred-whitered&&+gitmergewhite&&+gitwrite-tree>/dev/null||{+echo"BAD: merge did not complete"+return1+}++test-fB||{+echo"BAD: B does not exist in working directory"+return1+}+test-fN||{+echo"BAD: N does not exist in working directory"+return1+}+test-fR||{+echo"BAD: R does not exist in working directory"+return1+}++test-fA&&{+echo"BAD: A still exists in working directory"+return1+}+test-fM&&{+echo"BAD: M still exists in working directory"+return1+}+return0+'++test_done
From: Johannes Schindelin <hidden> Date: 2016-08-11 20:40:47
Hi,
On Wed, 13 Dec 2006, Shawn O. Pearce wrote:
quoted hunk
Prior to 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae we deleted a
file from the working directory during a merge if the file existed
in the working directory before the merge started but was renamed
by the branch which is being merged in. This broke in 65ac63 as
git-merge-recursive did not actually update the working directory
on this uncontested rename case.
[...]
@@ -873,7 +873,7 @@ static int process_renames(struct path_list *a_renames,structdiff_filespecsrc_other,dst_other;inttry_merge,stage=a_renames==renames1?3:2;-remove_file(1,ren1_src,1);+remove_file(1,ren1_src,0);
I _think_ that the "0" should be "!index_only". After all, these functions
are not only called on the virtual merges, but also on the final merge,
which indeed should update the working directory. And since it is a
rename, the old file has to go.
Ciao,