On Thu, Feb 22, 2018 at 10:04 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote: > Julius Musseau <julius@xxxxxxxxxxxxx> writes: > >> git squash [<commit>] >> >> Squashes <commit>..HEAD into a single commit. Replaces HEAD with the >> result. If not specified, <commit> defaults to the current branch's >> upstream (a.k.a. @{upstream}). >> >> Rationale: >> >> This command provides an intuitive mechanism for in-place squash that >> doesn't drop dirty merge results. >> >> We call this an in-place squash because the state of all files and >> directories at HEAD does not change. Only the ancestory of HEAD >> changes: its (only) parent becomes the merge-base of <commit> and >> HEAD, removing all intermediate commits. > > So is it essentially the same as > > git reset --soft $(git merge-base $commit HEAD) > git commit > > with some icing for coming up with a default log message? The above > won't touch the working tree at all. > > Yes! I had no idea about this approach. Thanks! My implementation uses "git commit-tree". Yes, some icing to build the squashed log message, as well as some protection to ensure the working tree is clean before doing the squash (just like "git rebase" does). I'm also working on two more pieces of icing: - Adding an "--oldest-author" flag to help adjust the author for the squashed commit (using the author value from the oldest commit in the squash). By "oldest" I mean whatever "git log --reverse --no-merges -1 <commit>..HEAD" spits out. (I don't consider timestamps.) - Ability to arbitrarily squash any branch by taking a 2nd "branch" argument. (And making the command work with bare repos.) I'm embarrassed to realise your approach matches the top-voted stack-overflow answer on the subject: https://stackoverflow.com/a/5201642 Nonetheless, the top-voted stack-overflow comment to that answer says: > Ha! I like this method. It is the one closes to the spirit of the problem. It's a pity that it requires so much voodoo. Something like this should be added to one of the basic commands. Should I proceed?