Map

git history: safer history rewrites in core git

Wiki summarygitdeveloper-toolsversion-control โ†ณ show in map Markdown
title
git history: safer history rewrites in core git
type
summary
summary
New experimental git subcommand โ€” fixup, reword, split โ€” that rewrites old commits and autorebases all branches, atomically
tags
git, developer-tools, version-control
created
2026-07-18
updated
2026-07-18

git history is an experimental subcommand that landed in core git across two releases: 2.54 (April 2026) brought reword and split, and 2.55 (June 2026) added fixup. It packages three common interactive-rebase workflows as their own lower-friction commands. Lalit's post frames it as a way to get some of what draws people to jj without leaving git โ€” and without installing anything, since it ships in the standard distribution.

The three subcommands all do the same underlying thing: edit an old commit and rebuild everything on top of it. Rewriting a commit changes its hash, so every descendant gets re-created with a new hash and every local branch tip that pointed into that range moves to follow. That reach goes further than git rebase --update-refs, which only moves refs sitting inside the range being rebased โ€” git history finds and rewrites every local branch descended from the target commit, with an option to limit the effect to the current branch.

fixup folds staged changes into an older commit. You git add the fix as usual, then git history fixup <commit> squashes it in โ€” like git commit --fixup plus an autosquash rebase, except it also updates any other branch that contained the commit.

reword rewrites an old commit's message. It opens your editor with the existing message; you edit, save, and the stack is rebuilt on top. Because it only touches the message, it never touches your index or working tree.

split breaks one commit into two. It drops you into a hunk-by-hunk prompt over the commit's diff (like git add -p); the hunks you keep become the first commit, the rest fall into the second. This is the most specialized of the three but avoids the rebase gymnastics the same result would otherwise need.

The atomic guarantee, and its cost

The property tying all three together is that they are atomic โ€” the operation never leaves the tree in a half-broken mid-rebase state. Git buys this by refusing anything that could produce a conflict. It also refuses to run in the presence of merge commits, which rules the command out for some workflows.

This is deliberately less capable than jj, which treats conflicts as first-class and can carry a conflicted state through a rebase to be sorted out later. The git history docs are explicit that the no-conflict limitation is by design because history rewrites aren't meant to be stateful, and note it "can be lifted once (if) Git learns about first-class conflicts." So the ceiling may rise later. reword and split also work purely on the commit graph, so you can rewrite a commit on a branch you don't have checked out without disturbing whatever you're in the middle of.

git history doesn't close the whole gap to jj โ€” there's still no operation log with easy undo, no modelling of the working copy as a commit, and no conflict-carrying rebase. But it puts several of the attractive pieces into the tool most people already use.

This is squarely git-history tooling, adjacent to the committed-file behaviors in git-magic-files and to the analytical takes on git history in pgit and linux-kernel-pgit, though those query history rather than rewrite it.

Interesting from the discussion

nine_k's one-line summary: newer git turned three frequent uses of git rebase --interactive into separate lower-friction commands that only work when there are no conflicts.

A recurring read was that this is a safer stepping stone rather than a replacement. WorldMaker argued that developers already comfortable with git rebase may never need it, but for teaching juniors it's a good, safe on-ramp for a handful of common tasks โ€” juniors tend to learn rebase's footguns faster than its capabilities. paularmstrong expects git history split to help juniors break large PRs into smaller ones, and wished it could split an entire branch in two.

Several commenters pushed back on the article's premise that rebases are scary, pointing at the existing safety nets: git rebase --abort, the reflog, mybranch@{1} for a branch's previous location, and the habit of setting a throwaway before-rebase branch or tag first. The counterpoint from skydhash was that conflicts are a signal that two commits' intent differs, and fearing them usually means not understanding the changes well enough โ€” which spun off a long, pointed argument about whether git's UX problems are real or just "git gud" gatekeeping, including klibertp's quip that git is the Dark Souls of version control.