# git history: safer history rewrites in core git

`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`](https://github.com/jj-vcs/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.
