Subject: Re: [PATCH v2 08/10] sparse-index: complete partial expansion

From: Junio C Hamano <[email-masked]>
Date: Mon, 23 May 2022 15:48:47 -0700

Derrick Stolee <[email-masked]> writes:

>> I suspect that is a situation that is not so uncommon.  Working
>> inside a narrow cone of a wide tree, performing a merge would
>> hopefully allow many subtrees that are outside of the cones of our
>> interest merged without getting expanded at all (e.g. only the other
>> side touched these subtrees we are not working on, so their version
>> will become the merge result), while changes to some paths in the
>> cone of our interest may result in true conflicts represented as
>> cache entries at higher stages, needing conflict resolution
>> concluded with "git add".  Having to expand these subtrees that we
>> managed to merge while still collapsed, only because we have
>> conflicts in some other parts of the tree, feels somewhat sad.
>
> You are correct that conflicts outside of the sparse-checkout cone will
> cause index expansion. That happens during the 'git merge' command, but
> the index will continue to fail to collapse as long as those conflicts
> still exist in the index.
>
> When there are conflicts like this during the merge, then the index
> expansion is not as large of a portion of the command as normal, because
> the conflict resolution also takes some time to compute. The commands
> afterwards do take longer purely because of the expanded index.

I was imagining a situation more like "tech-writers only have
Documentation/ inside the cone of interest, attempt a pull from
somebody else, have conflicts inside Documentation/, but everything
else could be resolved cleanly without expanding the index".  If the
puller's tree is based on the pristine upstream release tag, and the
pullee's tree is based on a slightly newer version of upstream
snapshot, everything that happened outside Documentation/ in their
trees would fast-forward, so such a merge wouldn't have to expand
directories like "builtin/" or "contrib/" in the index and instead
can merge at the tree level, right?

On the other hand, ...

> However, this state is also not as common as you might think. If a user
> has a sparse-checkout cone specified, then they are unlikely to change
> files outside of the sparse-checkout cone. They would not be the reason
> that those files have a conflict. The conflicts would exist only if they
> are merging branches that had conflicts outside of the cone. Typically,
> any merge of external changes like this are of the form of "git pull" or
> "git rebase", in which case the conflicts are still "local" to the
> developer's changes.

... you seem to be talking about the opposite case (e.g. in the
above paragraph), where a conflict happens outside the cone of
interest of the person who is making a merge.  So, I am a bit
puzzled.

> You are right that there is additional work that could be done here,
> specifically allowing the cache tree to partially succeed and use the
> successfully generated trees to create sparse directory entries where
> possible. This was not viable before because we lacked the "partially
> expanded" index state. This series establishes the necessary vocabulary to
> do such an improvement later.
>> By the way, why are we passing the "--missing-ok" option to "git
>> write-tree" here?
>> 
>>> +	cache_tree_update(istate, WRITE_TREE_MISSING_OK);
>> 
>> The same question here.  We didn't say "missing trees are OK".  What
>> made it OK in this change?
>  
> Both of these additions of WRITE_TREE_MISSING_OK are not needed. I
> think I added them in an earlier version, thinking they were needed
> due to something in the Scalar functional tests. I confirmed just now
> that they are not needed for that. I will remove them.
>
> Thanks,
> -Stolee