Skip to content

Commit e4095da

Browse files
committed
Merge branch 'en/merge-recursive-skip-fix'
When the sparse checkout feature is in use, "git cherry-pick" and other mergy operations lost the skip_worktree bit when a path that is excluded from checkout requires content level merge, which is resolved as the same as the HEAD version, without materializing the merge result in the working tree, which made the path appear as deleted. This has been corrected by preserving the skip_worktree bit (and not materializing the file in the working tree). * en/merge-recursive-skip-fix: merge-recursive: preserve skip_worktree bit when necessary t3507: add a testcase showing failure with sparse checkout
2 parents d6628c9 + 2b75fb6 commit e4095da

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

merge-recursive.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3070,10 +3070,26 @@ static int merge_content(struct merge_options *o,
30703070
if (mfi.clean &&
30713071
was_tracked_and_matches(o, path, &mfi.oid, mfi.mode) &&
30723072
!df_conflict_remains) {
3073+
int pos;
3074+
struct cache_entry *ce;
3075+
30733076
output(o, 3, _("Skipped %s (merged same as existing)"), path);
30743077
if (add_cacheinfo(o, mfi.mode, &mfi.oid, path,
30753078
0, (!o->call_depth && !is_dirty), 0))
30763079
return -1;
3080+
/*
3081+
* However, add_cacheinfo() will delete the old cache entry
3082+
* and add a new one. We need to copy over any skip_worktree
3083+
* flag to avoid making the file appear as if it were
3084+
* deleted by the user.
3085+
*/
3086+
pos = index_name_pos(&o->orig_index, path, strlen(path));
3087+
ce = o->orig_index.cache[pos];
3088+
if (ce_skip_worktree(ce)) {
3089+
pos = index_name_pos(&the_index, path, strlen(path));
3090+
ce = the_index.cache[pos];
3091+
ce->ce_flags |= CE_SKIP_WORKTREE;
3092+
}
30773093
return mfi.clean;
30783094
}
30793095

t/t3507-cherry-pick-conflict.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,4 +392,17 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' '
392392
test_cmp expect actual
393393
'
394394

395+
test_expect_success 'cherry-pick preserves sparse-checkout' '
396+
pristine_detach initial &&
397+
test_config core.sparseCheckout true &&
398+
test_when_finished "
399+
echo \"/*\" >.git/info/sparse-checkout
400+
git read-tree --reset -u HEAD
401+
rm .git/info/sparse-checkout" &&
402+
echo /unrelated >.git/info/sparse-checkout &&
403+
git read-tree --reset -u HEAD &&
404+
test_must_fail git cherry-pick -Xours picked>actual &&
405+
test_i18ngrep ! "Changes not staged for commit:" actual
406+
'
407+
395408
test_done

0 commit comments

Comments
 (0)