merge-recursive: Improve handling of rename target vs. directory addition
When dealing with file merging and renames and D/F conflicts and possible criss-cross merges (how's that for a corner case?), we did not do a thorough job ensuring the index and working directory had the correct contents. Fix the logic in merge_content() to handle this. Also, correct some erroneous tests in t6022 that were expecting the wrong number of unmerged index entries. These changes fix one of the tests in t6042 (and almost fix another one from t6042 as well). Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Aug 11, 2011 at 23:20 UTC
51931bf08e7de1f597d36bc2fd38b5310b6da7dd
3 files changed
+25
-8
merge-recursive.c
+22
-5
@@ -1379,19 +1379,34 @@ static int merge_content(struct merge_options *o,
1379
reason = "submodule";
1380
output(o, 1, "CONFLICT (%s): Merge conflict in %s",
1381
reason, path);
1382
- if (involved_in_rename)
1382
+ if (involved_in_rename && !df_conflict_remains)
1383
update_stages(path, &one, &a, &b);
1384
}
1385
1386
if (df_conflict_remains) {
1387
char *new_path;
1388
- update_file_flags(o, mfi.sha, mfi.mode, path,
1389
- o->call_depth || mfi.clean, 0);
1388
+ if (o->call_depth) {
1389
+ remove_file_from_cache(path);
1390
+ } else {
1391
+ if (!mfi.clean)
1392
+ update_stages(path, &one, &a, &b);
1393
+ else {
1394
+ int file_from_stage2 = was_tracked(path);
1395
+ struct diff_filespec merged;
1396
+ hashcpy(merged.sha1, mfi.sha);
1397
+ merged.mode = mfi.mode;
1398
+
1399
+ update_stages(path, NULL,
1400
+ file_from_stage2 ? &merged : NULL,
1401
+ file_from_stage2 ? NULL : &merged);
1402
+ }
1403
+
1404
+ }
1405
new_path = unique_path(o, path, df_rename_conflict_branch);
1391
- mfi.clean = 0;
1406
output(o, 1, "Adding as %s instead", new_path);
1393
- update_file_flags(o, mfi.sha, mfi.mode, new_path, 0, 1);
1407
+ update_file(o, 0, mfi.sha, mfi.mode, new_path);
1408
free(new_path);
1409
+ mfi.clean = 0;
1410
} else {
1411
update_file(o, mfi.clean, mfi.sha, mfi.mode, path);
1412
}
@@ -1580,6 +1595,8 @@ static int process_df_entry(struct merge_options *o,
1595
output(o, 1, "CONFLICT (%s): There is a directory with name %s in %s. "
1596
"Adding %s as %s",
1597
conf, path, other_branch, path, new_path);
1598
+ if (o->call_depth)
1599
+ remove_file_from_cache(path);
1600
update_file(o, 0, sha, mode, new_path);
1601
if (o->call_depth)
1602
remove_file_from_cache(path);
t/t6022-merge-rename.sh
+2
-2
@@ -307,7 +307,7 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' '
307
grep "Auto-merging dir" output &&
308
grep "Adding as dir~HEAD instead" output &&
309
310
- test 2 -eq "$(git ls-files -u | wc -l)" &&
310
+ test 3 -eq "$(git ls-files -u | wc -l)" &&
311
test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
312
313
test_must_fail git diff --quiet &&
@@ -329,7 +329,7 @@ test_expect_success 'Same as previous, but merged other way' '
329
grep "Auto-merging dir" output &&
330
grep "Adding as dir~renamed-file-has-no-conflicts instead" output &&
331
332
- test 2 -eq "$(git ls-files -u | wc -l)" &&
332
+ test 3 -eq "$(git ls-files -u | wc -l)" &&
333
test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
334
335
test_must_fail git diff --quiet &&
t/t6042-merge-rename-corner-cases.sh
+1
-1
@@ -234,7 +234,7 @@ test_expect_success 'setup content merge + rename/directory conflict' '
234
git commit -m left
235
'
236
237
-test_expect_failure 'rename/directory conflict + clean content merge' '
237
+test_expect_success 'rename/directory conflict + clean content merge' '
238
git reset --hard &&
239
git reset --hard &&
240
git clean -fdqx &&