Subject: Re: [PATCH 2/2] builtin/history: introduce "fixup" subcommand

From: Patrick Steinhardt <[email-masked]>
Date: Fri, 24 Apr 2026 08:53:45 +0200

On Thu, Apr 23, 2026 at 05:18:50PM -0400, D. Ben Knoble wrote:
> On Thu, Apr 23, 2026 at 2:55 AM Patrick Steinhardt <[email-masked]> wrote:
> > On Wed, Apr 22, 2026 at 03:06:12PM -0400, D. Ben Knoble wrote:
> > > On Wed, Apr 22, 2026 at 6:30 AM Patrick Steinhardt <[email-masked]> wrote:
> > > > diff --git a/Documentation/git-history.adoc b/Documentation/git-history.adoc
> > > > index 24dc907033..3cdfc8ba02 100644
> > > > --- a/Documentation/git-history.adoc
> > > > +++ b/Documentation/git-history.adoc
> > > > @@ -53,6 +55,19 @@ COMMANDS
> > > >
> > > >  The following commands are available to rewrite history in different ways:
> > > >
> > > > +`fixup <commit>`::
> > > > +       Apply the currently staged changes to the specified commit. The staged
> > > > +       changes are incorporated into the target commit's tree via a three-way
> > > > +       merge, using HEAD's tree as the merge base, which is equivalent to
> > > > +       linkgit:git-cherry-pick[1].
> > >
> > > I'm not quite sure what, as a user of "git history fixup," I'm
> > > supposed to take from this. Does it make conflicts less likely when
> > > creating the new fixup? I imagine it doesn't help with conflicts
> > > between <commit> and HEAD that newly arise.
> > >
> > > Anyway, I'd think the mechanics are less relevant than the end-user
> > > behavior at this point in the doc, unless the equivalence with
> > > cherry-pick is supposed to tell me something about that behavior.
> >
> > There's at least two more or less obvious variants to do this:
> >
> >   - You generate the diff between HEAD and index and then try to reapply
> >     the patch on top of the target commit.
> >
> >   - You perform the three-way merge.
> >
> > The second item is definitely more robust compared to generating the
> > diff and reapplying it, and we use the exact same strategy to perform
> > cherry-picks nowadays.
> >
> > > > diff --git a/builtin/history.c b/builtin/history.c
> > > > index 549e352c74..6299f0dfa9 100644
> > > > --- a/builtin/history.c
> > > > +++ b/builtin/history.c
> > [snip]
> > > > +       /*
> > > > +        * Perform the three-way merge to reapply changes in the index onto the
> > > > +        * target commit. This is using basically the same logic as a
> > > > +        * cherry-pick, where the base commit is our HEAD, ours is the original
> > > > +        * tree and theirs is the index tree.
> > > > +        */
> > >
> > > OTOH, this explanation helps quite a bit here :)
> >
> > Hm, okay. I felt that this explanation here is even more technical. How
> > about:
> >
> >     `fixup <commit>`::
> >         Apply the currently staged changes to the specified commit. This
> >         is done by performing a three-way merge between the HEAD commit,
> >         the target commit and the tree generated from staged changes.
> >         This is using the same logic as linkgit:git-cherry-pick[1].
> >
> > Not sure that this is an improvement? Happy to hear other suggestions.
> >
> > Thanks!
> >
> > Patrick
> 
> Hm. I think what I meant is that the in-code comment makes sense to
> describe internals; for users, I'm not sure what I should get out of
> that description of fixup.
> 
> What I (think I) really care about is that it behaves a bit like `git
> rebase -i` with a "fixup" command (modulo conflicts). Especially since
> this is quite a bit more porcelain than plumbing, no?
> 
> Idk. If the 3-way merge is valuable to keep, maybe it belongs in a
> second paragraph just to push it out of the way of the primary
> description ("Apply the currently staged changes to the specified
> commit")?

Ah, that's what you're getting at! I totally misunderstood what you
wanted to say, this makes a lot more sense. How about this:

    `fixup <commit>`::
        Apply the currently staged changes to the specified commit. This
        is similar in nature to `git commit --fixup=<commit>` followed
        by `git rebase --autosquash <commit>~`. Changes are applied to
        the target commit by performing a three-way merge between the
        HEAD commit, the target commit and the tree generated from
        staged changes.

Maybe there should be a new paragraph before we start talking about the
technical details?

Thanks!

Patrick