merge-recursive: Avoid unnecessary file rewrites

Often times, a potential conflict at a path is resolved by merge-recursive by using the content that was already present at that location. In such cases, we do not want to overwrite the content that is already present, as that could trigger unnecessary recompilations. One of the patches earlier in this series ("merge-recursive: When we detect we can skip an update, actually skip it") fixed the cases that involved content merges, but there were a few other cases 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 35a74abff32c32c455a74974130ad2af7d81dfd9
2 files changed +27 -9
merge-recursive.c
+24 -6
@@ -1036,7 +1036,14 @@ static void handle_change_delete(struct merge_options *o,
1036 change_past, o->branch1, o->branch1, path,
1037 NULL == renamed ? "" : " at ",
1038 NULL == renamed ? "" : renamed);
1039 - update_file(o, 0, a_sha, a_mode, renamed ? renamed : path);
1039 + if (renamed)
1040 + update_file(o, 0, a_sha, a_mode, renamed);
1041 + /*
1042 + * No need to call update_file() on path when !renamed, since
1043 + * that would needlessly touch path. We could call
1044 + * update_file_flags() with update_cache=0 and update_wd=0,
1045 + * but that's a no-op.
1046 + */
1047 }
1048 free(renamed);
1049 }
@@ -1396,10 +1403,20 @@ static int process_renames(struct merge_options *o,
1403 NULL);
1404 } else if ((dst_other.mode == ren1->pair->two->mode) &&
1405 sha_eq(dst_other.sha1, ren1->pair->two->sha1)) {
1399 - /* Added file on the other side
1400 - identical to the file being
1401 - renamed: clean merge */
1402 - update_file(o, 1, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst);
1406 + /*
1407 + * Added file on the other side identical to
1408 + * the file being renamed: clean merge.
1409 + * Also, there is no need to overwrite the
1410 + * file already in the working copy, so call
1411 + * update_file_flags() instead of
1412 + * update_file().
1413 + */
1414 + update_file_flags(o,
1415 + ren1->pair->two->sha1,
1416 + ren1->pair->two->mode,
1417 + ren1_dst,
1418 + 1, /* update_cache */
1419 + 0 /* update_wd */);
1420 } else if (!sha_eq(dst_other.sha1, null_sha1)) {
1421 clean_merge = 0;
1422 try_merge = 1;
@@ -1727,7 +1744,8 @@ static int process_entry(struct merge_options *o,
1744 free(new_path);
1745 } else {
1746 output(o, 2, "Adding %s", path);
1730 - update_file(o, 1, sha, mode, path);
1747 + /* do not overwrite file if already present */
1748 + update_file_flags(o, sha, mode, path, 1, !a_sha);
1749 }
1750 } else if (a_sha && b_sha) {
1751 /* Case C: Added in both (check for same permissions) and */
t/t6022-merge-rename.sh
+3 -3
@@ -696,7 +696,7 @@ test_expect_success 'setup avoid unnecessary update, dir->(file,nothing)' '
696 git commit -m "Add a newfile"
697 '
698
699 -test_expect_failure 'avoid unnecessary update, dir->(file,nothing)' '
699 +test_expect_success 'avoid unnecessary update, dir->(file,nothing)' '
700 git checkout -q master^0 &&
701 test-chmtime =1000000000 df &&
702 test-chmtime -v +0 df >expect &&
@@ -726,7 +726,7 @@ test_expect_success 'setup avoid unnecessary update, modify/delete' '
726 git commit -m "Modify file"
727 '
728
729 -test_expect_failure 'avoid unnecessary update, modify/delete' '
729 +test_expect_success 'avoid unnecessary update, modify/delete' '
730 git checkout -q master^0 &&
731 test-chmtime =1000000000 file &&
732 test-chmtime -v +0 file >expect &&
@@ -755,7 +755,7 @@ test_expect_success 'setup avoid unnecessary update, rename/add-dest' '
755 git commit -m "Rename file"
756 '
757
758 -test_expect_failure 'avoid unnecessary update, rename/add-dest' '
758 +test_expect_success 'avoid unnecessary update, rename/add-dest' '
759 git checkout -q master^0 &&
760 test-chmtime =1000000000 newfile &&
761 test-chmtime -v +0 newfile >expect &&