DEV Community

Ashraf
Ashraf

Posted on

Git History Command: The Safer Way to Split, Reword, and Fixup Commits

Git History Command: The Safer Way to Split, Reword, and Fixup Commits

The git history command is an experimental addition to core Git for the work developers routinely do after the code is already written: split one messy commit, reword an old commit, or fix up a change without reaching immediately for a terrifying interactive rebase.

It is not a replacement for Git. It is a sharper set of scalpels for repairing Git history—and it is worth knowing about before you switch your entire workflow to Jujutsu (jj).

A Hacker News discussion pushed this command onto the front page today, with 372 points and 249 comments when checked. The timing is useful: the feature is new enough to be overlooked, but old enough to have landed across Git 2.54 and 2.55.

What is the git history command?

git history is an experimental command family documented by Git. The current subcommands are:

  • fixup — fold a commit's changes into another commit
  • reword — change a commit message
  • split — interactively divide a commit into multiple commits

The feature arrived incrementally. Git's 2.54 release notes added reword and split; Git 2.55 added fixup.

That matters because the command is not available in every Git installation. My current environment reports Git 2.39.5, so blindly copying these commands there will fail. Check first:

git --version
Enter fullscreen mode Exit fullscreen mode

Use a recent Git build that includes the command, and remember the warning in the official documentation: this is experimental behavior, not a promise that the interface will never change.

Why git history beats a panic-driven interactive rebase

Interactive rebase is powerful. It is also a command where a small mistake can turn a straightforward cleanup into a recovery exercise involving reflogs, detached HEADs, and increasingly desperate searches through Stack Overflow.

The usual workflow looks like this:

git rebase -i <parent>
Enter fullscreen mode Exit fullscreen mode

Then you edit a list of commits and hope the operation does exactly what you intended. That is fine when you are comfortable with rebase's state machine. It is less fine when you are fixing one specific commit in a branch with parallel work, merges, or references you do not want to disturb.

git history makes the intent explicit. You ask Git to split this commit, reword that commit, or fix up this commit. The command is still rewriting history—do not confuse a nicer interface with a risk-free operation—but the operation maps more directly to the job in your head.

How to use git history split

Suppose HEAD contains a commit that combines a refactor and a test update. You want two commits instead of one:

git history split HEAD
Enter fullscreen mode Exit fullscreen mode

Git interactively lets you choose the hunks to move into the new split-out commit. The remaining changes stay in the original commit, whose parent is updated to the newly created commit.

You can limit the split to a pathspec when only one part of a large commit needs surgery:

git history split HEAD -- src/auth/
Enter fullscreen mode Exit fullscreen mode

The important mental model is that you are not merely staging the current working tree. You are editing the shape of an existing commit. Treat the result as a history rewrite and inspect it immediately:

git log --oneline --decorate -5
git show --stat HEAD
git diff HEAD~2..HEAD
Enter fullscreen mode Exit fullscreen mode

Do this before pushing. If the branch is already shared, coordinate with everyone who has based work on it.

How to use git history reword

Bad commit message? Fix it directly:

git history reword <commit>
Enter fullscreen mode Exit fullscreen mode

This is the boring operation, which is exactly why it is useful. A clear commit message improves git log, release-note generation, blame investigations, and the next engineer's ability to understand why a change exists.

Use it to turn messages like this:

fix stuff
Enter fullscreen mode Exit fullscreen mode

into something that carries actual information:

retry token refresh after a transient 401
Enter fullscreen mode Exit fullscreen mode

Do not rewrite commits that are already part of a public branch merely to satisfy aesthetics. A clean private branch is a good target. A force-pushed shared branch is a team incident waiting to happen.

How to use git history fixup

To fold a commit into an earlier commit, run:

git history fixup <commit>
Enter fullscreen mode Exit fullscreen mode

The command is conceptually similar to creating a fixup! commit and then running an interactive rebase with autosquash, but the intent is packaged as one history operation. The official documentation also exposes a --dry-run option for the history subcommands, so use it when you want to inspect the proposed operation before committing to it:

git history fixup <commit> --dry-run
Enter fullscreen mode Exit fullscreen mode

The exact output and behavior can evolve while the command remains experimental. Read the version of the official documentation installed with your Git rather than assuming a blog post from another release is authoritative.

Git history vs. Jujutsu

The feature exists in the same problem space that makes Jujutsu attractive: developers want to manage a stream of changes without constantly wrestling with the index, temporary commits, and rebase choreography.

Jujutsu is still a distinct version-control system with a different model. git history is much less ambitious. It keeps you inside Git's object database, remotes, hosting integrations, and team conventions while improving a few high-friction history edits.

That is the pragmatic appeal:

  • no repository migration
  • no new hosting workflow
  • no new mental model for everyday branching
  • no need to teach the whole team a different VCS to get better commit surgery

If your pain is specifically “I need to split, rename, or fold this commit,” try the narrow tool first. Do not adopt a new version-control system to solve a problem a built-in command already addresses.

A safe workflow for rewriting history

History editing is still history editing. Use guardrails:

1. Create a recovery reference

Before experimenting, create a temporary branch or tag:

git branch before-history-edit
Enter fullscreen mode Exit fullscreen mode

If the result is wrong, the original commit graph still has a name.

2. Run the operation on a private branch

Never start by rewriting main, a release branch, or a branch other people are actively using.

3. Prefer dry runs

Where supported, use --dry-run first. Then inspect the proposed commit graph and file changes.

4. Check the graph, not only the working tree

A clean working tree does not prove that the history is correct:

git log --graph --oneline --decorate --all -15
git diff before-history-edit..HEAD
Enter fullscreen mode Exit fullscreen mode

5. Push rewritten history deliberately

If the branch is already remote, use the least dangerous force option available to your workflow:

git push --force-with-lease origin feature/my-change
Enter fullscreen mode Exit fullscreen mode

--force-with-lease is not magic, but it refuses to overwrite a remote update you have not seen. That is a much better default than --force.

The sharp opinion

Git has spent years accumulating commands that expose its internals while leaving common history edits to a cryptic interactive todo list. git history is a welcome correction.

The feature does not make rewriting commits safe. It makes the requested operation legible. That is a meaningful improvement: fewer accidental rebases, fewer “what did I just do?” moments, and less pressure to migrate tools because Git's porcelain made a simple job feel like surgery with a chainsaw.

Try it on a disposable branch. Read the version-specific docs. Keep the reflog and a recovery reference. Then decide whether git history earns a place in your daily workflow.

Sources

Top comments (0)