Skip to content

Commit d7c9bf2

Browse files
Martin von Zweigbergkgitster
authored andcommitted
diffcore-rename: don't consider unmerged path as source
Since e9c8409 (diff-index --cached --raw: show tree entry on the LHS for unmerged entries., 2007-01-05), an unmerged entry should be detected by using DIFF_PAIR_UNMERGED(p), not by noticing both one and two sides of the filepair records mode=0 entries. However, it forgot to update some parts of the rename detection logic. This only makes difference in the "diff --cached" codepath where an unmerged filepair carries information on the entries that came from the tree. It probably hasn't been noticed for a long time because nobody would run "diff -M" during a conflict resolution, but "git status" uses rename detection when it internally runs "diff-index" and "diff-files" and gives nonsense results. In an unmerged pair, "one" side can have a valid filespec to record the tree entry (e.g. what's in HEAD) when running "diff --cached". This can be used as a rename source to other paths in the index that are not unmerged. The path that is unmerged by definition does not have the final content yet (i.e. "two" side cannot have a valid filespec), so it can never be a rename destination. Use the DIFF_PAIR_UNMERGED() to detect unmerged filepair correctly, and allow the valid "one" side of an unmerged filepair to be considered a potential rename source, but never to be considered a rename destination. Commit message and first two test cases by Junio, the rest by Martin. Signed-off-by: Martin von Zweigbergk <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent da656f1 commit d7c9bf2

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

diffcore-rename.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ void diffcore_rename(struct diff_options *options)
439439
else
440440
locate_rename_dst(p->two, 1);
441441
}
442-
else if (!DIFF_FILE_VALID(p->two)) {
442+
else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {
443443
/*
444444
* If the source is a broken "delete", and
445445
* they did not really want to get broken,
@@ -574,7 +574,10 @@ void diffcore_rename(struct diff_options *options)
574574
struct diff_filepair *p = q->queue[i];
575575
struct diff_filepair *pair_to_free = NULL;
576576

577-
if (!DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
577+
if (DIFF_PAIR_UNMERGED(p)) {
578+
diff_q(&outq, p);
579+
}
580+
else if (!DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
578581
/*
579582
* Creation
580583
*

t/t7060-wtstatus.sh

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,66 @@ test_expect_success 'M/D conflict does not segfault' '
5656
)
5757
'
5858

59+
test_expect_success 'rename & unmerged setup' '
60+
git rm -f -r . &&
61+
cat "$TEST_DIRECTORY/README" >ONE &&
62+
git add ONE &&
63+
test_tick &&
64+
git commit -m "One commit with ONE" &&
65+
66+
echo Modified >TWO &&
67+
cat ONE >>TWO &&
68+
cat ONE >>THREE &&
69+
git add TWO THREE &&
70+
sha1=$(git rev-parse :ONE) &&
71+
git rm --cached ONE &&
72+
(
73+
echo "100644 $sha1 1 ONE" &&
74+
echo "100644 $sha1 2 ONE" &&
75+
echo "100644 $sha1 3 ONE"
76+
) | git update-index --index-info &&
77+
echo Further >>THREE
78+
'
79+
80+
test_expect_success 'rename & unmerged status' '
81+
git status -suno >actual &&
82+
cat >expect <<-EOF &&
83+
UU ONE
84+
AM THREE
85+
A TWO
86+
EOF
87+
test_cmp expect actual
88+
'
89+
90+
test_expect_success 'git diff-index --cached shows 2 added + 1 unmerged' '
91+
cat >expected <<-EOF &&
92+
U ONE
93+
A THREE
94+
A TWO
95+
EOF
96+
git diff-index --cached --name-status HEAD >actual &&
97+
test_cmp expected actual
98+
'
99+
100+
test_expect_success 'git diff-index --cached -M shows 2 added + 1 unmerged' '
101+
cat >expected <<-EOF &&
102+
U ONE
103+
A THREE
104+
A TWO
105+
EOF
106+
git diff-index --cached --name-status HEAD >actual &&
107+
test_cmp expected actual
108+
'
109+
110+
test_expect_success 'git diff-index --cached -C shows 2 copies + 1 unmerged' '
111+
cat >expected <<-EOF &&
112+
U ONE
113+
C ONE THREE
114+
C ONE TWO
115+
EOF
116+
git diff-index --cached -C --name-status HEAD |
117+
sed "s/^C[0-9]*/C/g" >actual &&
118+
test_cmp expected actual
119+
'
120+
59121
test_done

0 commit comments

Comments
 (0)