Subject: Re: [PATCH v2 1/7] reset: behave correctly with sparse-checkout

From: Victoria Dye <[email-masked]>
Date: Tue, 5 Oct 2021 17:59:28 -0400

Junio C Hamano wrote:
> Wouldn't a fix to the situation be to 
> 
>  * Add the blob for "skip" taken from the initial commit to the
>    index, just like the entry for "no-skip" is updated;
> 
>  * But remember that "skip" was marked with "skip-worktree" bit
>    immediately before "git reset" was asked to do its thing, and
>    re-add the bit to the path in the index before "git reset" gives
>    the control back to the usre;
> 
>  * And keep the working tree untouched, without writing anything out
>    to "skip".  If the user had a (possibly unrelated) file there, it
>    will not be overwritten, and if the user left the path absent, it
>    will still be absent.
> 
> so that the last three diagnostic commands in the above sample
> sequence would instead read:
> 
>     $ ls *skip
>     no-skip
>     $ git ls-files -t
>     M no-skip
>     S skip
>     $ git status -suno
>      M no-skip
> 
> i.e. skip gets updated in the index only, nothing changes in the
> working tree for "skip" or "no-skip", and status reports that
> "no-skip" is different from the index but "skip" hasn't changed in
> the working tree since the index (thanks to its skip-worktree bit).
> 
> Then the user will be happy in the same way as the user was happy
> immediately after the state marked with "There is no 'reset' done
> yet so far." above, on both counts, not just for "status does not
> report something got changed" part but also "user didn't want to see
> 'skip' in the working tree, and 'skip' did not materialize" part.
> 
> Thanks.
> 

Thanks for the thorough explanation, I'm on-board with your approach (and
will re-roll the series with that implemented). A lot of my thought process
(and confusion) came from a comment in e5ca291076 (t1092: document bad
sparse-checkout behavior, 2021-07-14) suggesting that full and sparse
checkouts should have the same result in scenarios like the one you
outlined above. The problem is, as noted earlier, it's impossible to tell
whether (using your example):

1. the user deleted `skip` because they intentionally want to remove it from
   the worktree, and it should continue to be deleted after a reset.
2. `skip` doesn't exist in the worktree because it's excluded from the
   sparse checkout definition and the user does not want its current state
   "deleted" after a reset.

As a result, there's no way `git reset --mixed` could be expected to behave
the same way in full checkouts as it does in sparse, and the most consistent
solution is that the worktree should remain untouched with `skip-worktree`
preserved.