The Operation Log
One of JJ’s killer features is the operation log—a complete history of every action you’ve taken in your repository. This is your safety net that makes JJ safe to experiment with.
What is the Operation Log?
Every time you run a JJ command that modifies the repository, JJ creates an operation that records:
- What command you ran
- The complete state of the repository before and after
- When it happened
- Any commit changes that resulted
The operation log is not just for commits—it tracks everything:
jj new- Creating commitsjj edit- Changing which commit you’re working onjj rebase- Moving commits aroundjj squash- Combining commitsjj describe- Updating commit messagesjj abandon- Removing commits- Even
jj undoitself!
As one developer put it: “Version control finally entered the 1960s” (a reference to having undo/redo in modern applications).
Viewing Your Operation History
See what you’ve done:
jj op logOutput shows each operation:
@ a8c4d9e7 user@host 2024-01-15 14:23:19 -08:00│ rebase commit xyz│ args: jj rebase -s xyz -d main○ b7f3a2c1 user@host 2024-01-15 14:20:45 -08:00│ new empty commit│ args: jj new -m "Add feature"○ c9e1b4d3 user@host 2024-01-15 14:15:32 -08:00│ describe commit abc│ args: jj describe -m "Update message"Each operation has an ID (like a8c4d9e7) that you can use to restore or examine that point in history.
The Simple Undo
Made a mistake? Undo it:
jj undoThis reverses the last operation. You can run it multiple times:
jj undo # Undo last operationjj undo # Undo the one before thatjj undo # Keep going backWhat You Can Undo
Everything:
- Bad rebase?
jj undo - Abandoned the wrong commit?
jj undo - Squashed commits by mistake?
jj undo - Resolved conflicts wrong?
jj undo - Accidentally deleted a bookmark?
jj undo
There’s no limit to what jj undo can reverse. Research shows this is mentioned in 14 out of 20 major JJ guides as a transformative feature.
Time Travel with jj op restore
Want to jump to a specific point in history rather than undoing one step at a time?
# View your operation logjj op log
# Restore to a specific operationjj op restore b7f3a2c1This restores your entire repository state to that operation—all commits, bookmarks, working copy, everything.
Real-World Scenarios
Scenario 1: Bad Rebase
# Rebase your stackjj rebase -s stack -d trunk# Oh no! Conflicts everywhere and I messed it up
# No problem - undojj undo# Back to before the rebaseScenario 2: Accidentally Abandoned Commits
# View commitsjj log -r stacks
# Abandon what you thought was an empty commitjj abandon xyz# Oh no! That had important work!
# Restore itjj undo# The commit is back with all its changesScenario 3: Wrong Conflict Resolution
# Resolve conflictsjj resolve# ... make choices ...# Wait, I resolved that wrong
# Undo the resolutionjj undo# Conflicts are back, can resolve againScenario 4: Experimenting with Stack Reorganization
# Try a complex rebasejj rebase -s commit-a -d commit-bjj squash -r commit-cjj rebase -s commit-d -d commit-e
# Hmm, that didn't work out how I wanted
# Undo all of itjj undojj undojj undo# Or restore to before you started:jj op restore <op-id-before-experiment>Understanding Operation IDs
Each operation gets a unique ID. JJ shows you the ID when you run commands:
$ jj rebase -s xyz -d mainRebased 3 commitsWorking copy now at: qpvuntsmAdded 0 files, modified 1 files, removed 0 filesOperation ID: a8c4d9e7You can use these IDs with jj op restore to return to exact moments in time.
The Operation Log vs Git’s Reflog
Git has a git reflog feature, but it’s much more limited:
| Git Reflog | JJ Operation Log |
|---|---|
| Tracks HEAD movements only | Tracks every repository change |
| Separate reflog per branch | One unified history |
| Entries expire (default 90 days) | Permanent history |
| Hard to understand output | Clear command history |
| Can’t restore complex states | Full state restoration |
In Git, recovering from mistakes requires understanding reachability, detached HEAD states, and manual git reset/git cherry-pick operations.
In JJ, you just jj undo or jj op restore.
Why This Enables Fearless Refactoring
The operation log fundamentally changes how you interact with version control:
Before (Git mentality):
- “Let me carefully plan this rebase”
- “I better create a backup branch just in case”
- “What if I mess up the conflict resolution?”
- Fear leads to avoiding powerful operations
After (JJ mentality):
- “Let me try this rebase and see what happens”
- “I can always undo if it doesn’t work”
- “Experiment first, commit to the approach after”
- Safety enables exploration
Research across 20+ guides shows developers consistently report being more willing to experiment once they trust jj undo.
Operation Log Limitations
A few things to know:
-
Operations are local - They don’t sync to remotes. If you clone a repo, you start with a fresh operation log.
-
Undo works on operations, not time - If you run three commands quickly, you need three undos (or use
jj op restore). -
Can’t undo pushes to remote - Once you push to GitHub, that’s permanent (though you can always force-push corrections).
Practical Tips
Before Risky Operations
Check your current operation ID:
jj op log --limit 1Save that ID. If things go wrong, you can jj op restore <id> to get back.
Viewing Operation Details
See exactly what changed in an operation:
jj op show a8c4d9e7This shows all commits that were added, modified, or removed.
Cleaning Old Operations (Advanced)
Operations accumulate over time. To clean up very old operations:
jj op abandon <old-op-id>This removes operations before that ID. Only do this if you’re sure you won’t need to restore to those states.
Next Steps
Now that you trust JJ’s safety net:
- Understand the Mental Model of how JJ works
- Read Common Mistakes to avoid pitfalls
- Try First-Class Conflicts knowing you can undo
The operation log makes JJ one of the safest version control systems ever created. Experiment freely!
Ernesto Jiménez