Skip to content

Commit 3f047ee

Browse files
newrenbenpeart
authored andcommitted
merge-recursive: preserve skip_worktree bit when necessary
merge-recursive takes any files marked as unmerged by unpack_trees, tries to figure out whether they can be resolved (e.g. using renames or a file-level merge), and then if they can be it will delete the old cache entries and writes new ones. This means that any ce_flags for those cache entries are essentially cleared when merging. Unfortunately, if a file was marked as skip_worktree and it needs a file-level merge but the merge results in the same version of the file that was found in HEAD, we skip updating the worktree (because the file was unchanged) but clear the skip_worktree bit (because of the delete-cache-entry-and-write-new-one). This makes git treat the file as having a local change in the working copy, namely a delete, when it should appear as unchanged despite not being present. Avoid this problem by copying the skip_worktree flag in this case. Signed-off-by: Elijah Newren <[email protected]>
1 parent f8acb80 commit 3f047ee

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

merge-recursive.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3043,10 +3043,26 @@ static int merge_content(struct merge_options *o,
30433043
if (mfi.clean &&
30443044
was_tracked_and_matches(o, path, &mfi.oid, mfi.mode) &&
30453045
!df_conflict_remains) {
3046+
int pos;
3047+
struct cache_entry *ce;
3048+
30463049
output(o, 3, _("Skipped %s (merged same as existing)"), path);
30473050
if (add_cacheinfo(o, mfi.mode, &mfi.oid, path,
30483051
0, (!o->call_depth && !is_dirty), 0))
30493052
return -1;
3053+
/*
3054+
* However, add_cacheinfo() will delete the old cache entry
3055+
* and add a new one. We need to copy over any skip_worktree
3056+
* flag to avoid making the file appear as if it were
3057+
* deleted by the user.
3058+
*/
3059+
pos = index_name_pos(&o->orig_index, path, strlen(path));
3060+
ce = o->orig_index.cache[pos];
3061+
if (ce_skip_worktree(ce)) {
3062+
pos = index_name_pos(&the_index, path, strlen(path));
3063+
ce = the_index.cache[pos];
3064+
ce->ce_flags |= CE_SKIP_WORKTREE;
3065+
}
30503066
return mfi.clean;
30513067
}
30523068

t/t3507-cherry-pick-conflict.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' '
392392
test_cmp expect actual
393393
'
394394

395-
test_expect_failure 'cherry-pick preserves sparse-checkout' '
395+
test_expect_success 'cherry-pick preserves sparse-checkout' '
396396
pristine_detach initial &&
397397
test_config core.sparseCheckout true &&
398398
test_when_finished "

0 commit comments

Comments
 (0)