Skip to content

Commit

Permalink
merge-recursive: Avoid unnecessary file rewrites
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Elijah Newren authored and Junio C Hamano committed Aug 14, 2011
1 parent 3e333a6 commit 35a74ab
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 9 deletions.
30 changes: 24 additions & 6 deletions merge-recursive.c
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,14 @@ static void handle_change_delete(struct merge_options *o,
change_past, o->branch1, o->branch1, path,
NULL == renamed ? "" : " at ",
NULL == renamed ? "" : renamed);
update_file(o, 0, a_sha, a_mode, renamed ? renamed : path);
if (renamed)
update_file(o, 0, a_sha, a_mode, renamed);
/*
* No need to call update_file() on path when !renamed, since
* that would needlessly touch path. We could call
* update_file_flags() with update_cache=0 and update_wd=0,
* but that's a no-op.
*/
}
free(renamed);
}
Expand Down Expand Up @@ -1396,10 +1403,20 @@ static int process_renames(struct merge_options *o,
NULL);
} else if ((dst_other.mode == ren1->pair->two->mode) &&
sha_eq(dst_other.sha1, ren1->pair->two->sha1)) {
/* Added file on the other side
identical to the file being
renamed: clean merge */
update_file(o, 1, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst);
/*
* Added file on the other side identical to
* the file being renamed: clean merge.
* Also, there is no need to overwrite the
* file already in the working copy, so call
* update_file_flags() instead of
* update_file().
*/
update_file_flags(o,
ren1->pair->two->sha1,
ren1->pair->two->mode,
ren1_dst,
1, /* update_cache */
0 /* update_wd */);
} else if (!sha_eq(dst_other.sha1, null_sha1)) {
clean_merge = 0;
try_merge = 1;
Expand Down Expand Up @@ -1727,7 +1744,8 @@ static int process_entry(struct merge_options *o,
free(new_path);
} else {
output(o, 2, "Adding %s", path);
update_file(o, 1, sha, mode, path);
/* do not overwrite file if already present */
update_file_flags(o, sha, mode, path, 1, !a_sha);
}
} else if (a_sha && b_sha) {
/* Case C: Added in both (check for same permissions) and */
Expand Down
6 changes: 3 additions & 3 deletions t/t6022-merge-rename.sh
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ test_expect_success 'setup avoid unnecessary update, dir->(file,nothing)' '
git commit -m "Add a newfile"
'

test_expect_failure 'avoid unnecessary update, dir->(file,nothing)' '
test_expect_success 'avoid unnecessary update, dir->(file,nothing)' '
git checkout -q master^0 &&
test-chmtime =1000000000 df &&
test-chmtime -v +0 df >expect &&
Expand Down Expand Up @@ -726,7 +726,7 @@ test_expect_success 'setup avoid unnecessary update, modify/delete' '
git commit -m "Modify file"
'

test_expect_failure 'avoid unnecessary update, modify/delete' '
test_expect_success 'avoid unnecessary update, modify/delete' '
git checkout -q master^0 &&
test-chmtime =1000000000 file &&
test-chmtime -v +0 file >expect &&
Expand Down Expand Up @@ -755,7 +755,7 @@ test_expect_success 'setup avoid unnecessary update, rename/add-dest' '
git commit -m "Rename file"
'

test_expect_failure 'avoid unnecessary update, rename/add-dest' '
test_expect_success 'avoid unnecessary update, rename/add-dest' '
git checkout -q master^0 &&
test-chmtime =1000000000 newfile &&
test-chmtime -v +0 newfile >expect &&
Expand Down

0 comments on commit 35a74ab

Please sign in to comment.