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

Re: [PATCH 2/2] builtin/stash: merge index in-core

From
D. Ben Knoble <ben.knoble@gmail.com>
Date
Sep 22, 2026, 12:43 UTC
Message-ID
<CALnO6CDG4Emny7xESxN8GObaXb_P9gPHBZ857hrAvDjiMSqsKQ@mail.gmail.com>
In-Reply-To
<2551b801-4cb3-4880-ac01-7d14a188ddd4@gmail.com>
On Mon, Sep 21, 2026 at 9:17 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
Show 13 quoted lines
>
> Hi Ben
>
> On 19/09/2026 22:26, D. Ben Knoble wrote:
> > Fortunately, we can achieve 2 goals at once: avoid round-tripping to the
> > file-system (and invoking expensive subprocesses) by performing the
> > merge in-core. Since the results are never seen, we don't need to set
> > the usual branch and ancestor labels.
>
> When the merge succeeds without conflicts we use the result so it is
> seen. It would be clearer to say that "If there are conflicts we discard
> the result so ...". The rest of the commit message explains the problem
> nicely.

Indeed. This is what I get for (unusually) dashing off the commit message up against the clock. Thanks!

Show 17 quoted lines
> > @@ -669,29 +625,25 @@ static enum stash_apply_result do_apply_stash(const char *prefix,
> >                   oideq(&c_tree, &info->i_tree)) {
> >                       has_index = 0;
> >               } else {
> > -                     struct strbuf out = STRBUF_INIT;
> > +                     struct merge_result result = { 0 };
> >
> > -                     if (diff_tree_binary(&out, &info->w_commit)) {
> > -                             strbuf_release(&out);
> > -                             return error(_("could not generate diff %s^!."),
> > -                                          oid_to_hex(&info->w_commit));
> > -                     }
> > +                     init_basic_merge_options(&o, the_repository);
>
> This means we potentially use different diff algorithms when merging the
> index and when merging the work tree, let's use the _ui variant here
> instead.

Yep, you know I'd spotted that and wasn't expecting it to make a meaningful difference. It's an easy swap, but I thought that (like above, since we don't show the conflict results) the diff algorithm wouldn't matter too much.

Maybe it affects the actual merge-ability, though, in which case I agree using the same is important?

Show 5 quoted lines
> > +                     o.verbosity = 0;
>
> Looking at the code in merge-ort.c it appears the verbosity option was
> used by the recursive strategy but isn't used anymore so I think we
> could drop this.

Intriguing. (Assuming the default "2") There's a "< 5" check in path_msg() that wouldn't be affected by dropping this, and a "> 2" check in checkout() that… also wouldn't be affected?

But it might matter if something is setting the verbosity elsewhere (config, GIT_MERGE_VERBOSITY), and I think we really want this merge to be quiet? I seem to remember reading commits in this area quieting "git reset" and so on to keep the noise down.

So I'm inclined to leave it for now, especially in case it later does get used.
Show 6 quoted lines
> > +                     oidcpy(&index_tree, &result.tree->object.oid);
> > +                     clear_merge_options(&o);
>
> Looking at replay.c:replay_revisions() I think this should be
>
> merge_finalize(&opts, &result);

Hm, possibly. It does look like that does more with the "result," which is probably needed. But it doesn't actually clear the merge options.

On one hand, I thought it could be important not to reuse that struct between merges. But if we do use the "ui" init, it might be ok? replay_revisions() does use the same struct between calls to merge_incore_nonrecursive().

Oh, but one other thing: we unconditionally reinit the merge options later on in do_apply_stash(). We could conditionally initialize there ("if (has_index)"), I suppose?

Show 21 quoted lines
> > diff --git a/merge-ort.c b/merge-ort.c
> > index c410a5d353..f69a49d48a 100644
> > --- a/merge-ort.c
> > +++ b/merge-ort.c
> > @@ -5035,8 +5035,6 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
> >       trace2_region_enter("merge", "sanity checks", opt->repo);
> >       assert(opt->repo);
> >
> > -     assert(opt->branch1 && opt->branch2);
>
> This, and the hunk below, make me nervous. Normally assertions like this
> exist because the pointers are unconditionally dereferenced later on.
> Looking at merge_3way() it asserts opt->ancestor is non-NULL and
> dereferences all three labels. t3903 does not appear to have test
> coverage for the index merge failing (if it did I think we'd see a
> SIGSEV), we should probably add a test that checks the command fails
> leaving the index and work tree untouched, and verifies the message on
> stderr.
>
> Lets set some simple, fixed, ancestor and branch names in
> do_apply_stash() above.

Funny, I was getting aborts before removing the asserts because I hadn't set the labels, aha. Looks like we've come back around to keeping the labels. I'll probably keep a similar structure as the working tree merge uses, I think.

A fail-to-merge test also seems like a good idea. Let me mull on that.
Thanks for the review.
-- 
D. Ben Knoble
Previous: Phillip WoodNext: D. Ben Knoble
Message 6 of 78 in “Hi all,”
  1. 0/2 Hi all,D. Ben Knoble, Sep 19, 2026
  2. 1/2 builtin/stash: remove unused headerD. Ben Knoble, Sep 19, 2026
  3. Junio C HamanoSep 21, 2026
  4. 2/2 builtin/stash: merge index in-coreD. Ben Knoble, Sep 19, 2026
  5. Phillip WoodSep 21, 2026
  6. D. Ben KnobleSep 22, 2026
  7. D. Ben KnobleSep 22, 2026
  8. Phillip WoodSep 22, 2026
  9. D. Ben KnobleSep 22, 2026
  10. D. Ben KnobleSep 19, 2026
  11. 0/4 stash: clean up index-mode test mergeD. Ben Knoble, Sep 23, 2026
  12. 1/4 builtin/stash: remove unused headerD. Ben Knoble, Sep 23, 2026
  13. 2/4 stash: prepare merge options earlierD. Ben Knoble, Sep 23, 2026
  14. 3/4 t: test failed "stash apply --index"D. Ben Knoble, Sep 23, 2026
  15. Phillip WoodSep 24, 2026
  16. D. Ben KnobleSep 25, 2026
  17. Phillip WoodSep 25, 2026
  18. Phillip WoodSep 26, 2026
  19. D. Ben KnobleSep 26, 2026
  20. 4/4 builtin/stash: merge index in-coreD. Ben Knoble, Sep 23, 2026
  21. Phillip WoodSep 24, 2026
  22. D. Ben KnobleSep 25, 2026
  23. Phillip WoodSep 25, 2026
  24. D. Ben KnobleSep 25, 2026
  25. Junio C HamanoSep 24, 2026
  26. Junio C HamanoSep 25, 2026
  27. D. Ben KnobleSep 25, 2026
  28. Junio C HamanoSep 25, 2026
  29. Phillip WoodSep 26, 2026
  30. D. Ben KnobleSep 26, 2026
  31. Phillip WoodSep 25, 2026
  32. D. Ben KnobleSep 25, 2026
  33. Junio C HamanoSep 25, 2026
  34. 0/5 stash: clean up index-mode test mergeD. Ben Knoble, Sep 26, 2026
  35. 1/5 builtin/stash: remove unused headerD. Ben Knoble, Sep 26, 2026
  36. 2/5 stash: prepare merge options earlierD. Ben Knoble, Sep 26, 2026
  37. 3/5 t3903: test stash --index mergesD. Ben Knoble, Sep 26, 2026
  38. Phillip WoodSep 28, 2026
  39. D. Ben KnobleSep 28, 2026
  40. Phillip WoodSep 29, 2026
  41. 4/5 t3903: test failed "stash apply --index"D. Ben Knoble, Sep 26, 2026
  42. 5/5 builtin/stash: merge index in-coreD. Ben Knoble, Sep 26, 2026
  43. Junio C HamanoSep 27, 2026
  44. D. Ben KnobleSep 28, 2026
  45. Junio C HamanoSep 28, 2026
  46. D. Ben KnobleSep 28, 2026
  47. Junio C HamanoSep 28, 2026
  48. D. Ben KnobleSep 26, 2026
  49. Junio C HamanoSep 27, 2026
  50. Phillip WoodSep 28, 2026
  51. D. Ben KnobleSep 28, 2026
  52. D. Ben KnobleSep 28, 2026
  53. D. Ben KnobleSep 28, 2026
  54. Phillip WoodSep 28, 2026
  55. Thomas BachemSep 28, 2026
  56. D. Ben KnobleSep 28, 2026
  57. D. Ben KnobleSep 29, 2026
  58. Phillip WoodSep 29, 2026
  59. Phillip WoodSep 28, 2026
  60. 0/5 stash: clean up index-mode test mergeD. Ben Knoble, Sep 29, 2026
  61. 1/5 builtin/stash: remove unused headerD. Ben Knoble, Sep 29, 2026
  62. 2/5 stash: prepare merge options earlierD. Ben Knoble, Sep 29, 2026
  63. 3/5 t3903: test failed "stash apply --index"D. Ben Knoble, Sep 29, 2026
  64. 4/5 t5520: don't expire reflogs where it mattersD. Ben Knoble, Sep 29, 2026
  65. Phillip WoodSep 29, 2026
  66. 5/5 builtin/stash: merge index in-coreD. Ben Knoble, Sep 29, 2026
  67. Junio C HamanoSep 29, 2026
  68. D. Ben KnobleSep 30, 2026
  69. Phillip WoodSep 29, 2026
  70. Ben KnobleSep 29, 2026
  71. D. Ben KnobleSep 30, 2026
  72. 0/4 stash: clean up index-mode test mergeD. Ben Knoble, Sep 30, 2026
  73. 1/4 builtin/stash: remove unused headerD. Ben Knoble, Sep 30, 2026
  74. 3/4 t3903: test failed "stash apply --index"D. Ben Knoble, Sep 30, 2026
  75. 2/4 stash: prepare merge options earlierD. Ben Knoble, Sep 30, 2026
  76. 4/4 builtin/stash: merge index in-coreD. Ben Knoble, Sep 30, 2026
  77. Phillip WoodOct 1, 2026
  78. Junio C HamanoOct 1, 2026

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.