Subject: Re: [PATCH v5 02/17] sparse-checkout: create 'init' subcommand

From: SZEDER Gábor <[email-masked]>
Date: Thu, 21 Nov 2019 16:27:44 +0100

On Thu, Nov 21, 2019 at 09:28:59AM -0500, Derrick Stolee wrote:
> On 11/21/2019 6:49 AM, SZEDER Gábor wrote:
> > On Mon, Oct 21, 2019 at 01:56:11PM +0000, Derrick Stolee via GitGitGadget wrote:
> >> Getting started with a sparse-checkout file can be daunting. Help
> >> users start their sparse enlistment using 'git sparse-checkout init'.
> >> This will set 'core.sparseCheckout=true' in their config, write
> >> an initial set of patterns to the sparse-checkout file, and update
> >> their working directory.
> > 
> > Enabling sparse-checkout can remove modified files:
> > 
> >   $ mkdir dir
> >   $ touch foo dir/bar
> >   $ git add .
> >   $ git commit -m Initial
> >   [master (root-commit) ecc81bd] Initial
> >    2 files changed, 0 insertions(+), 0 deletions(-)
> >    create mode 100644 dir/bar
> >    create mode 100644 foo
> >   $ echo changes >dir/bar
> >   $ ~/src/git/git sparse-checkout init
> >   error: Entry 'dir/bar' not uptodate. Cannot update sparse checkout.
> >   error: failed to update index with new sparse-checkout paths
> >   $ cat dir/bar 
> >   changes
> > 
> > So far so good, my changes are still there.  Unfortunately, however:
> > 
> >   $ git add -u
> >   $ ~/src/git/git sparse-checkout init
> >   $ echo $?
> >   0
> >   $ ls
> >   foo
> > 
> > Uh-oh, my changes are gone.
> 
> Here, your changes are not "lost", they are staged, correct? 

Well, yes, the changes were staged, so they must be in the object
database somewhere, the user just has to go through the dangling
objects reported by 'git fsck' to find and restore it...  So from the
perspective of an ordinary user they are lost.

> A "git status"
> should report that your changes are ready for committing. This seems to be
> the expected behavior.

No, unfortunately enabling sparse-checkout did throw the staged
changes away:

  ~/test (master +)$ ~/src/git/git sparse-checkout init
  ~/test (master)$ git status 
  On branch master
  nothing to commit, working tree clean

Note also the shell prompt going from "you have staged changes" to
"working tree is clean".

But wait, I thought that only changes to files that are excluded from
the sparse-checkout are thrown away, but as it turns out it throws
away changes to files that are included in the sparse-checkout:

  ~/test (master #)$ echo original >foo
  ~/test (master #%)$ git add .
  ~/test (master +)$ git commit -m Initial
  [master (root-commit) 04cb2a2] Initial
   1 file changed, 1 insertion(+)
   create mode 100644 foo
  ~/test (master)$ echo changes >foo 
  ~/test (master *)$ ~/src/git/git sparse-checkout init
  ~/test (master *)$ cat foo 
  changes

So far so good, but:

  ~/test (master *)$ ~/src/git/git sparse-checkout disable
  ~/test (master *)$ git add .
  ~/test (master +)$ ~/src/git/git sparse-checkout init
  ~/test (master)$ cat foo 
  original

This is not really sparse-checkout-specific, because this is what 'git
read-tree -um HEAD' always does on its own:

  ~/test (master)$ echo changes >foo 
  ~/test (master *)$ git read-tree -um HEAD
  ~/test (master *)$ cat foo 
  changes
  ~/test (master *)$ git add -u
  ~/test (master +)$ git read-tree -um HEAD
  ~/test (master)$ cat foo 
  original

These issues are present at the end of the patch series as well, but
that is sort-of expected, because the later commit message states
that:

    Remove this extra process call by creating a direct call to
    unpack_trees() in the same way 'git read-tree -mu HEAD' does.