Amending
Important
You see how Jujutsu takes
git commit --amendand makes it universal.
Found a typo in your last commit?
A---B---C <- main (HEAD)
Easy: git commit --amend. Voilà!
A---B---C' <- main (HEAD)
This is an elegant abstraction. Commits are immutable, so amend
actually creates a new commit with the same parent, then resets the
branch:
A---B---C
\
C' <- main (HEAD)
Git pulls a fast one, giving you the impression the last commit was
editable. Under the hood, git commit --amend is equivalent to
something like:
git reset --hard HEAD^
git cherry-pick -n ORIG_HEAD
git add .
git commit -C ORIG_HEAD
But you don’t need to know! This is the beauty of amend: it captures
your intention and hides the mechanics. Neat!
Leaky abstraction
How do you amend the second-to-last commit? There’s no git commit --amend HEAD~1. You need a terrifying sequence of checkouts,
cherry-picks, and branch resets. The abstraction tears, revealing the
gears beneath.
What about amending Y here?
A---B---C---D---E---F
\ /
X---Y---Z
Oh beautiful abstraction, where art thou?
More consistent abstraction
When you amend, your intention is to edit a commit. The underlying metaphor is: The last commit is editable.
Can we make this universal? Imagine jj edit modifying any point in history.
- Want to amend
C?jj edit C. - Want to amend
Y?jj edit Y.
We return to intuitive UX. jj edit captures the what and manages the internal how. Editing Y cascades changes to Z, E, and F automatically.
In practice
- Install Jujutsu.
- Run
jj git initin your Git repo. It safely coexists with Git. - Need to amend a commit deep in history?
jj edit <SHA1>
# Do your changes
git checkout <your-branch>
I’m lying slightly. You might hit conflicts, so keep reading. But I hope you just had your first a-ha moment.