Subject: [PATCH 00/13] [RFC] Sparse-checkout: modify 'git add', 'git rm', and 'git add' behavior

From: "Derrick Stolee via GitGitGadget" <[email-masked]>
Date: Tue, 24 Aug 2021 21:54:32 +0000

As requested, this series looks to update the behavior of git add, git rm,
and git mv when they attempt to modify paths outside of the sparse-checkout
cone. In particular, this care is expanded to not just cache entries with
the SKIP_WORKTREE bit, but also paths that do not match the sparse-checkout
definition.

This means that commands that worked before this series can now fail. In
particular, if 'git merge' results in a conflict outside of the
sparse-checkout cone, then 'git add ' will now fail.

In order to allow users to circumvent these protections, a new '--sparse'
option is added that ignores the sparse-checkout patterns and the
SKIP_WORKTREE bit. The message for advice.updateSparsePath is adjusted to
assist with discovery of this option.

There is a subtle issue with git mv in that it does not check the index
until it discovers a directory and then uses the index to find the contained
entries. This means that in non-cone-mode patterns, a pattern such as
"sub/dir" will not match the path "sub" and this can cause an issue.

In order to allow for checking arbitrary paths against the sparse-checkout
patterns, some changes to the underlying pattern matching code is required.
It turns out that there are some bugs in the methods as advertised, but
these bugs were never discovered because of the way methods like
unpack_trees() will check a directory for a pattern match before checking
its contained paths. Our new "check patterns on-demand" approach pokes holes
in that approach, specifically with patterns that match entire directories.

I'm open to alternative designs here, too.

The patches are based on v2 of the integration with merge, cherry-pick, and
rebase. I'm sending the RFC really early in case it needs to be
significantly reworked.

Thanks, -Stolee

Derrick Stolee (13):
  t1092: behavior for adding sparse files
  dir: extract directory-matching logic
  dir: select directories correctly
  dir: fix pattern matching on dirs
  add: fail when adding an untracked sparse file
  add: skip paths that are outside sparse-checkout cone
  add: implement the --sparse option
  add: prevent adding sparse conflict files
  rm: add --sparse option
  rm: skip sparse paths with missing SKIP_WORKTREE
  mv: refuse to move sparse paths
  mv: add '--sparse' option to ignore sparse-checkout
  advice: update message to suggest '--sparse'

 Documentation/git-add.txt                |   9 +-
 Documentation/git-rm.txt                 |   6 ++
 advice.c                                 |   3 +-
 builtin/add.c                            |  22 ++++-
 builtin/mv.c                             |  39 ++++++--
 builtin/rm.c                             |  10 +-
 dir.c                                    |  54 ++++++++--
 pathspec.c                               |   5 +-
 t/t1091-sparse-checkout-builtin.sh       |   4 +-
 t/t1092-sparse-checkout-compatibility.sh |  47 ++++++---
 t/t3602-rm-sparse-checkout.sh            |  27 ++++-
 t/t3705-add-sparse-checkout.sh           |  10 +-
 t/t7002-mv-sparse-checkout.sh            | 121 +++++++++++++++++++++++
 13 files changed, 316 insertions(+), 41 deletions(-)
 create mode 100755 t/t7002-mv-sparse-checkout.sh

base-commit: df4bbec744f5cd4a060082212d95a36b812fa50b
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1018%2Fderrickstolee%2Fsparse-index%2Fadd-rm-mv-behavior-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1018/derrickstolee/sparse-index/add-rm-mv-behavior-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1018
-- 
gitgitgadget