"Derrick Stolee via GitGitGadget" <gitgitgadget@xxxxxxxxx> writes: > + if (pl && !pl->use_cone_patterns) { > pl = NULL; > + } else { > + /* > + * We might contract file entries into sparse-directory > + * entries, and for that we will need the cache tree to > + * be recomputed. > + */ > + cache_tree_free(&istate->cache_tree); > + > + /* > + * If there is a problem creating the cache tree, then we > + * need to expand to a full index since we cannot satisfy > + * the current request as a sparse index. > + */ > + if (cache_tree_update(istate, WRITE_TREE_MISSING_OK)) > + pl = NULL; > + } So, if the current index has some irrelevant (i.e. do not match the pattern list) subtrees in collapsed form, presense of an unmerged entry, presumably inside the cone(s) we are interested in, makes us lose the pattern list here, and we end up expanding everything? 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. By the way, why are we passing the "--missing-ok" option to "git write-tree" here? > @@ -330,11 +352,22 @@ void expand_to_pattern_list(struct index_state *istate, > struct cache_entry *ce = istate->cache[i]; > struct tree *tree; > struct pathspec ps; > + int dtype; > > if (!S_ISSPARSEDIR(ce->ce_mode)) { > set_index_entry(full, full->cache_nr++, ce); > continue; > } > + > + /* We now have a sparse directory entry. Should we expand? */ > + if (pl && > + path_matches_pattern_list(ce->name, ce->ce_namelen, > + NULL, &dtype, > + pl, istate) == NOT_MATCHED) { > + set_index_entry(full, full->cache_nr++, ce); > + continue; > + } > + > if (!(ce->ce_flags & CE_SKIP_WORKTREE)) > warning(_("index entry is a directory, but not sparse (%08x)"), > ce->ce_flags); > @@ -360,7 +393,7 @@ void expand_to_pattern_list(struct index_state *istate, > /* Copy back into original index. */ > memcpy(&istate->name_hash, &full->name_hash, sizeof(full->name_hash)); > memcpy(&istate->dir_hash, &full->dir_hash, sizeof(full->dir_hash)); > - istate->sparse_index = 0; > + istate->sparse_index = pl ? PARTIALLY_SPARSE : COMPLETELY_FULL; > free(istate->cache); > istate->cache = full->cache; > istate->cache_nr = full->cache_nr; > @@ -374,7 +407,7 @@ void expand_to_pattern_list(struct index_state *istate, > > /* Clear and recompute the cache-tree */ > cache_tree_free(&istate->cache_tree); > - cache_tree_update(istate, 0); > + 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?