Browse Source

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
maint
Junio C Hamano 6 years ago
parent
commit
e4095da40e
  1. 16
      merge-recursive.c
  2. 13
      t/t3507-cherry-pick-conflict.sh

16
merge-recursive.c

@ -3070,10 +3070,26 @@ static int merge_content(struct merge_options *o, @@ -3070,10 +3070,26 @@ static int merge_content(struct merge_options *o,
if (mfi.clean &&
was_tracked_and_matches(o, path, &mfi.oid, mfi.mode) &&
!df_conflict_remains) {
int pos;
struct cache_entry *ce;

output(o, 3, _("Skipped %s (merged same as existing)"), path);
if (add_cacheinfo(o, mfi.mode, &mfi.oid, path,
0, (!o->call_depth && !is_dirty), 0))
return -1;
/*
* However, add_cacheinfo() will delete the old cache entry
* and add a new one. We need to copy over any skip_worktree
* flag to avoid making the file appear as if it were
* deleted by the user.
*/
pos = index_name_pos(&o->orig_index, path, strlen(path));
ce = o->orig_index.cache[pos];
if (ce_skip_worktree(ce)) {
pos = index_name_pos(&the_index, path, strlen(path));
ce = the_index.cache[pos];
ce->ce_flags |= CE_SKIP_WORKTREE;
}
return mfi.clean;
}


13
t/t3507-cherry-pick-conflict.sh

@ -392,4 +392,17 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' ' @@ -392,4 +392,17 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' '
test_cmp expect actual
'

test_expect_success 'cherry-pick preserves sparse-checkout' '
pristine_detach initial &&
test_config core.sparseCheckout true &&
test_when_finished "
echo \"/*\" >.git/info/sparse-checkout
git read-tree --reset -u HEAD
rm .git/info/sparse-checkout" &&
echo /unrelated >.git/info/sparse-checkout &&
git read-tree --reset -u HEAD &&
test_must_fail git cherry-pick -Xours picked>actual &&
test_i18ngrep ! "Changes not staged for commit:" actual
'

test_done

Loading…
Cancel
Save