The git history command
Rediscovering the git history Command
Managing a multitude of parallel changes in Git can often feel like a chore. You find yourself constantly juggling various branches and commits, occasionally resorting to terrifying rebase -i sequences that risk leaving your repository in a fragmented state if a single mistake is made.
Many developers point toward jj (Jujutsu) as the modern solution to these woes. While the problems jj addresses are valid, the author finds the transition difficult; despite trying to integrate it every few months for the past year and a half, they always revert to Git.
However, there is a hidden gem within Git itself: the git history command.
What is git history?
This experimental feature was rolled out across two specific versions:
- Version 2.54 (April): Introduced
rewordandsplit. - Version 2.55 (June): Introduced
fixup.
Despite a brief spike in interest during the releases, the community hasn't discussed it much since. This is unfortunate because it provides many of the "quality of life" improvements associated with jj without requiring a total migration of your toolchain. Since it is part of the core Git distribution, no external installation is required.
🛠️ The Three Core Subcommands
1. git history fixup
This command allows you to correct an older commit and automatically rebase all descendant branches to maintain consistency.
The Workflow:
- Stage your corrections using
git add. - Execute
git history fixup <commit-hash>.
This functions similarly to a combination of git commit --fixup and an autosquash rebase, but with a critical advantage: it updates every local branch that descends from that commit. This is more powerful than git rebase --update-refs, which only affects references within the immediate rebase range.
Note: This command currently fails if merge commits are present, which may be a dealbreaker for some workflows.
Visualizing Fixup
In the diagram above, represents the original commit plus the staged fix. Because the hash changes, and must be recreated as and .
2. git history reword
If you need to update a commit message because the project's design evolved, reword is the tool for the job.
- Action:
git history reword <commit-hash> - Process: It opens your default editor you modify the text Git rebuilds the stack on top.
Unlike fixup, reword (and split) operates purely on the commit graph. It does not touch your index or working tree. This means you can rewrite a commit on a branch you aren't currently using without interrupting your current work.
3. git history split
This is perhaps the most specialized tool, acting like an interactive git add -p but without the complexity of a manual rebase.
When you run git history split <commit-hash>, Git provides a hunk-by-hunk prompt. The pieces you select form the first commit, and the remaining changes form the second.
🛡️ Atomicity and Conflict Handling
A defining characteristic of these commands is that they are atomic. They will never leave your working directory in a "half-broken" state.
How it works:
If an operation would result in a merge conflict, git history simply refuses to perform the action. While jj treats conflicts as first-class objects (allowing you to commit a conflicted state and resolve it later), Git does not yet.
Regarding this limitation, the documentation states:
"This limitation is by design as history rewrites are not intended to be stateful operations."
This suggests that if Git ever implements first-class conflicts, this limitation could be lifted.
Comparison: git history vs. jj
| Feature | git history | jj (Jujutsu) |
|---|---|---|
| Integrated in Git | ✅ | ❌ |
| Atomic Rewrites | ✅ | ✅ |
| Auto-updates branches | ✅ | ✅ |
| Operation Log/Undo | ❌ | ✅ |
| Working Copy as Commit | ❌ | ✅ |
| First-class Conflicts | ❌ | ✅ |
Final Thoughts
While git history doesn't fully bridge the gap to jj—missing features like the operation log and the "working copy as a commit" model—it is a significant leap forward. It brings highly desired functionality into the tool most of us already use daily.
Summary of capabilities:
- Fold fixes into old commits (
fixup) - Edit old messages without checking out branches (
reword) - Break large commits into smaller ones (
split) - Maintain branch pointer integrity automatically
The phrasing of the current documentation suggests that more enhancements are on the horizon, which is a promising sign for the future of Git's history management.