git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 0/7] Sparse index: integrate with 'git stash'

From
Elijah Newren <newren@gmail.com>
Date
May 6, 2022, 07:46 UTC
Message-ID
<CABPp-BFANwZn73w8zrVySB7mh0bQQBdGJjBuSJy50UOeyYT6aA@mail.gmail.com>
In-Reply-To
<pull.1171.v2.git.1651083378.gitgitgadget@gmail.com>

On Wed, Apr 27, 2022 at 11:16 AM Victoria Dye via GitGitGadget <gitgitgadget@gmail.com> wrote:

Show 5 quoted lines
>
> This series, in combination with the sparse index integrations of reset [1],
> update-index [2], checkout-index [2], clean [2], and read-tree [3], allows
> most subcommands of 'git stash' to use the sparse index end-to-end without
> index expansion.

I've read through the series. Like Stolee, I'm pleased with how simple some of the code changes are (much due to prior hard work in the area) and how nicely you describe the changes.

At first when I was reading through, I was again a bit disappointed that we're just converting the subcommands stash uses instead of fixing stash to stop forking subprocesses, but...then I realized this served as a forcing function of sorts to make more of Git sparse-index compatible, so I think it's actually the better route. We can always make the orthogonal fixes to stash's implementation design later. :-)

However, there is one small issue around the way merging is handled...
Show 79 quoted lines
> Like the earlier series, this series starts with new tests ensuring
> compatibility of the sparse index with non-sparse index full and sparse
> checkouts [1/7]. Next, sparse index is trivially enabled [2/7].
> Functionally, sparse index-enabled sparse-checkouts remain compatible with
> non-sparse index sparse-checkouts, but there are still some cases where the
> index (or a temporary index) is expanded unnecessarily. These cases are
> fixed in three parts:
>
>  * First, 'git stash -u' is made sparse index-compatible by ensuring the
>    "temporary" index holding the stashed, untracked files is created as a
>    sparse index whenever possible (per repo settings &
>    'is_sparse_index_allowed()'). Patch [3/7] exposes
>    'is_sparse_index_allowed()' to files outside of 'sparse-index.c', then
>    patch [4/7] uses that function to mark the temporary index sparse when
>    appropriate.
>  * Next, 'git stash (apply|pop)' are made sparse index-compatible by
>    changing their internal "merge" function (executed via
>    'merge_recursive_generic()') from 'merge_recursive()' to
>    'merge_ort_recursive()'. This requires first allowing
>    'merge_recursive_generic()' to accept a merge function as an input
>    (rather than hardcoding use of 'merge_recursive()') in patch [5/7], then
>    changing the call in 'stash.c' to specify 'merge_ort_recursive()' in
>    patch [6/7]. See note [4] for possible alternate implementations.
>  * Finally, while patches 5 & 6 avoid index expansion for most cases of 'git
>    stash (apply|pop)', applying a stash that includes untracked files still
>    expands the index. This is a result of an internal 'read-tree' execution
>    (specifically in its 'unpack_trees' call) creating a result index that is
>    never sparse in-core, thus forcing the index to be unnecessarily
>    collapsed and re-expanded in 'do_write_locked_index()'. In patch [7/7],
>    'unpack_trees' is updated to set the default sparsity of the resultant
>    index to "sparse" if allowed by repo settings and
>    'is_sparse_index_allowed()' (similar to the change in patch 4).
>
> Performance results (from the 'p2000' tests):
>
> (git stash &&
>  git stash pop)              master            this series
> ---------------------------------------------------------------------
> full-v3                      4.07(2.42+1.34)   3.98(2.42+1.32) -2.2%
> full-v4                      4.05(2.46+1.31)   4.00(2.49+1.29) -1.2%
> sparse-v3                    7.48(4.81+2.57)   1.53(0.26+1.61) -79.5%
> sparse-v4                    7.35(4.74+2.54)   1.59(0.27+1.63) -78.4%
>
> (echo >>new &&
>  git stash -u &&
>  git stash pop)              master            this series
> ---------------------------------------------------------------------
> full-v3                      4.21(2.62+1.45)   4.11(2.55+1.44) -2.4%
> full-v4                      4.11(2.51+1.41)   4.02(2.49+1.41) -2.2%
> sparse-v3                    7.35(4.64+2.66)   1.70(0.32+1.64) -76.9%
> sparse-v4                    7.74(4.87+2.83)   1.70(0.32+1.66) -78.0%
>
>
>
> Changes since V1
> ================
>
>  * Added quotes to the "$WITHOUT_UNTRACKED_TXT" when testing for it in
>    'ensure_not_expanded' (in 't/t1092-sparse-checkout-compatibility.sh')
>  * Moved the 'stash' test in 't1092' elsewhere in the file, so that it
>    doesn't conflict (even trivially) with the also-in-flight 'git show'
>    integration
>  * Moved the 'ensure_not_expended' tests for 'checkout-index' back to
>    original location
>
> [1]
> https://lore.kernel.org/git/pull.1048.v6.git.1638201164.gitgitgadget@gmail.com/
> [2]
> https://lore.kernel.org/git/pull.1109.v2.git.1641924306.gitgitgadget@gmail.com/
> [3]
> https://lore.kernel.org/git/pull.1157.v3.git.1646166271.gitgitgadget@gmail.com/
> [4] I went with changing 'stash' to always use 'merge-ort' in
> 'merge_recursive_generic()' as a sort of "middle ground" between "replace
> 'merge_recursive()' with 'merge_ort_recursive()' in all of its hardcoded
> internal usage" and "only use 'merge-ort' if using a sparse index in 'git
> stash', otherwise 'merge-recursive'". The former would extend the use of
> 'merge-ort' to 'git am' and 'git merge-recursive', whereas the latter is a
> more cautious/narrowly-focused option. If anyone has any other thoughts, I'm
> interested in hearing them.

I understand that you'd want to modify and use merge_recursive_generic() in order to make the smallest code change possible, but merge_recursive_generic() has no equivalent in ort because during the review of ort, we discovered that porting over merge_recursive_generic() meant porting bugs. We need to fix those bugs. However, in the case of stash, I think we can just sidestep those bugs. stash probably only uses merge_recursive_generic() because it was the easiest transliteration of shell (which originally invoked git-merge-recursive), as opposed to the best conversion. The best conversion at the time would have been to call merge_trees() instead (stash doesn't need recursiveness, and tends to have commits available rather than just trees). I'd like to see us modify stash to call merge_incore_nonrecursive() directly (and/or merge_trees() if we're supporting using both merge-ort and merge-recursive backends).

No need to worry about git-am or git-merge-recursive for now; we can replace/fix/update their calls to merge_recursive_generic() later.

Previous: Elijah NewrenNext: Victoria Dye via GitGitGadget
Message 30 of 42 in “Sparse index: integrate with 'git stash'”
  1. 0/7 Sparse index: integrate with 'git stash'Victoria Dye via GitGitGadget, Apr 25, 2022
  2. 1/7 stash: expand sparse-checkout compatibility testingVictoria Dye via GitGitGadget, Apr 25, 2022
  3. 3/7 sparse-index: expose 'is_sparse_index_allowed()'Victoria Dye via GitGitGadget, Apr 25, 2022
  4. 7/7 unpack-trees: preserve index sparsityVictoria Dye via GitGitGadget, Apr 25, 2022
  5. 6/7 stash: merge applied stash with merge-ortVictoria Dye via GitGitGadget, Apr 25, 2022
  6. Derrick StoleeApr 26, 2022
  7. 4/7 read-cache: set sparsity when index is newVictoria Dye via GitGitGadget, Apr 25, 2022
  8. Junio C HamanoApr 25, 2022
  9. 2/7 stash: integrate with sparse indexVictoria Dye via GitGitGadget, Apr 25, 2022
  10. Junio C HamanoApr 25, 2022
  11. Derrick StoleeApr 26, 2022
  12. Victoria DyeApr 26, 2022
  13. Junio C HamanoApr 26, 2022
  14. 5/7 merge-recursive: add merge function arg to 'merge_recursive_generic'Victoria Dye via GitGitGadget, Apr 25, 2022
  15. Junio C HamanoApr 25, 2022
  16. Derrick StoleeApr 26, 2022
  17. Derrick StoleeApr 26, 2022
  18. Derrick StoleeApr 26, 2022
  19. 0/7 Sparse index: integrate with 'git stash'Victoria Dye via GitGitGadget, Apr 27, 2022
  20. 1/7 stash: expand sparse-checkout compatibility testingVictoria Dye via GitGitGadget, Apr 27, 2022
  21. 2/7 stash: integrate with sparse indexVictoria Dye via GitGitGadget, Apr 27, 2022
  22. 3/7 sparse-index: expose 'is_sparse_index_allowed()'Victoria Dye via GitGitGadget, Apr 27, 2022
  23. 4/7 read-cache: set sparsity when index is newVictoria Dye via GitGitGadget, Apr 27, 2022
  24. 6/7 stash: merge applied stash with merge-ortVictoria Dye via GitGitGadget, Apr 27, 2022
  25. 7/7 unpack-trees: preserve index sparsityVictoria Dye via GitGitGadget, Apr 27, 2022
  26. 5/7 merge-recursive: add merge function arg to 'merge_recursive_generic'Victoria Dye via GitGitGadget, Apr 27, 2022
  27. Elijah NewrenMay 6, 2022
  28. Victoria DyeMay 9, 2022
  29. Elijah NewrenMay 10, 2022
  30. Elijah NewrenMay 6, 2022
  31. 0/6 Sparse index: integrate with 'git stash'Victoria Dye via GitGitGadget, May 10, 2022
  32. 1/6 stash: expand sparse-checkout compatibility testingVictoria Dye via GitGitGadget, May 10, 2022
  33. 2/6 stash: integrate with sparse indexVictoria Dye via GitGitGadget, May 10, 2022
  34. 3/6 sparse-index: expose 'is_sparse_index_allowed()'Victoria Dye via GitGitGadget, May 10, 2022
  35. 4/6 read-cache: set sparsity when index is newVictoria Dye via GitGitGadget, May 10, 2022
  36. 5/6 stash: apply stash using 'merge_ort_nonrecursive()'Victoria Dye via GitGitGadget, May 10, 2022
  37. Junio C HamanoMay 11, 2022
  38. Jonathan TanMay 12, 2022
  39. Elijah NewrenMay 12, 2022
  40. Jonathan TanMay 12, 2022
  41. Elijah NewrenMay 12, 2022
  42. 6/6 unpack-trees: preserve index sparsityVictoria Dye via GitGitGadget, May 10, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.