From: Phillip Wood Date: Mon, 29 Jun 2026 15:51:19 GMT Subject: Re: [PATCH v5 0/4] history: add squash subcommand to fold a range Message-ID: <3b3af3ef-a043-4af9-964e-429237789c97@gmail.com> In-Reply-To: Hi Harald and Patrick On 29/06/2026 07:26, Patrick Steinhardt wrote: > On Fri, Jun 26, 2026 at 09:52:57AM +0100, Phillip Wood wrote: >> Hi Harald >> >> On 24/06/2026 22:54, Harald Nordgren via GitGitGadget wrote: >>> Adds git history squash to fold a range of commits. >> >> It would be helpful to give a bit more detail here about the command so that >> the reader has an overview of what is actually being implemented. >> >> - what does it do with fixup!, squash! and amend! commits? Can it use >> the message from amend! commits to reword the commit? >> - can the user reword the commit message? > > Good things to document/discuss. Thanks, I was disappointed that these questions were not addressed in the cover letter for v6 which contains no more detail than this one. We should make rewording the commit as easy as possible to encourage users to create useful commit histories. I think that means having some support for fixup! style commits. We could just do what rebase does and comment out the fixup! style commit subjects and the commit messages replaced by amend! commits but I think we have the opportunity to do something nicer (I find the commented-out messages annoying). We could have a comment saying "this is the combination of the following commits" followed by a list of the subject lines and then in the template message we'd simply omit the useless fixup! subjects when the commit body is empty and also omit the original commit messages that have been replaced by an amend! commit. So instead of # This is the combination of 4 commits # This is the first commit message Base subject Base body # This is the second commit message # Another subject # Another body # This is the third commit message # fixup! Base subject # This is the fourth commit message # amend! Another subject A better subject A better body We'd have # This is the combination of 4 commits # 123 Base subject # 456 Another subject # 789 fixup! Base subject # abc amend! Another subject Base Subject Base Body Another subject Another Body Possibly with a comment before each message saying where it came from. It would be good to error out if the user tries squash a fixup! style commit and range does not contain its target commit. In the long run we should provide a way to squash an arbitrary list of commits rather than just a range. > >> - what happens if a merge commit inside the range has a parent outside >> the range? > > Yeah, I agree that we should punt on merge commits for now. They are a > can of worms, and I'm not sure that we should just squash them. I would > at least like the user to ask a flag that tells us that it's fine > squashing those. There does seem to be some support for merges in this patch series which I think behaves pretty sensibly. If we have C - D / \ - A - B - E - F - G Then squashing A..G should be fine because the parents of F are in the range and it looks like we support that. Squashing should B..G without --ancestry-path should be safe as well because B ends up as the parent of the squashed commit but we don't have a way to disable --ancestry-path (and maybe we don't want to add one). Squashing F^@..G might be useful to fixup a merge (though perhaps amending F rather than creating G is a simpler way to fix a broken merge). Squashing E..G does not make sense because the range does not include one of the merge parents. >> - what happens to branches that point to commits inside the range? > > Yeah, this should be documented indeed. > >> I had a quick play and found that it accepts ranges that containing a single >> commit (e.g. @^!) where there is nothing to squash. It also accepts ranges >> that are not ancestors of HEAD (e.g. checkout master and run "git history >> squash --dry-run origin/seen^2^!") without printing an error message. Only >> accepting a single argument is quite limiting as one cannot say >> >> git history squash ^:/base :/tip We should sanitize what the user passes though - we do not want to accept arbitrary rev-list options. Off the top of my head "--left-only" and "--right-only" would allow the use of "A...B" and allowing "--not" seems reasonable. > Note that it is intentional that you can rewrite branches that are not > currently checked out, and the other subcommands work the same. So I'd > argue this should also be the case for "squash". Ah, thanks for clarifying that - it does not seem to check that there is a branch to be rewritten though if I do ./git checkout origin/master ./git history squash --dry-run origin/seen^2^^..origin/seen^2 there is no error message and it exits 0. If I create a branch pointing at origin/seen^2 then it does print a sensible ref-update. Thanks Phillip