| name | jj |
| description | Jujutsu version control system. Use when working with jj repositories, commits, bookmarks, rebasing, conflicts, or git operations in jj context. Triggers on jj commands, revsets, or VCS workflows in jj-managed repos. |
Jujutsu (jj)
Git-compatible VCS with cleaner model. Working copy IS a commit (@). No staging area. Conflicts stored in commits. Full undo via operation log.
Targets jj 0.40 (see ~/jj/docs for source of truth).
Changes Are Rarely Lost
jj snapshots the repo state on every operation. Botched merge, bad rebase, accidental abandon — the previous state is recoverable for as long as the operation log retains it (default: 2 weeks, pruned by jj util gc):
jj op log
jj op restore OP_ID
Don't assume changes are lost after a failed operation. Before re-doing work or panicking, check jj op log and restore. Caveat: unsnapshotted working-copy edits (file changes since the last jj command) aren't in the op log — see gotchas.
Quick Reference
jj st
jj log
jj new [REV]
jj commit -m "msg"
jj describe -m "msg"
jj edit REV
jj squash
jj split
jj diff
jj rebase -s SRC -d DST
jj abandon REV
jj undo
jj op revert [OP]
jj git fetch
jj git push
jj git push --bookmark B
Core Concepts
Change ID vs Commit ID
- Change ID: Stable 12-letter ID (k-z), survives rewrites. Prefer this.
- Commit ID: SHA hash, changes on modification.
Working Copy = Commit
Working copy is commit @. Changes auto-amend it. No staging.
Bookmarks
Named pointers like git branches, with a different auto-move policy:
- Follow rewrites: amending/rebasing the bookmark's commit moves the bookmark automatically (bookmarks track change IDs).
- Don't follow new children:
jj new on top of a bookmark does not advance it.
Move manually when extending a branch:
jj bookmark move NAME --to @
jj bookmark advance
Revision Shortcuts
@ working copy
@- parent
@-- grandparent
::@ ancestors
@:: descendants
main..@ between main and @
Detailed Reference
Commands: See reference/commands.md for full command documentation
Revsets: See reference/revsets.md for revset operators and functions
Git Interop: See reference/git-interop.md for git clone, fetch, push workflows
Conflicts: See reference/conflicts.md for conflict markers and resolution
Configuration: See reference/config.md for settings and config files
Patterns & Workflows
Common Workflows: See patterns/workflows.md for git-to-jj translation and common patterns
Gotchas
jj workspace update-stale — use with care
Not actually data-loss prone, but easy to misread. See patterns/gotchas.md for the full walkthrough. TL;DR: it snapshots current edits onto the stale op, then checks out the desired @. Your edits survive — but they now live on a side branch in the op log, which is easy to mistake for "lost".
Snapshotting Is Not Automatic
jj does NOT snapshot on file changes alone — a jj command must run to trigger it. Run jj st periodically after edits to capture intermediate states in the operation log.
Bookmarks Don't Follow New Children
Bookmarks follow rewrites of their target (auto-amend, rebase) but not new commits on top:
jj edit feature
jj new
jj bookmark move feature --to @
Squash/Rebase Across Workspaces
Avoid rewriting commits that are ancestors of other workspaces' @. Rewrites the shared commit → other workspaces' working copies become stale, and their descendant commits rebase onto the new version (potential conflicts).
jj squash
jj new @ feature -m "merge"
Recovery: jj op log + jj op restore <op_id>, redo as merge.
Divergent Changes
Same change ID with multiple visible commits. A bare xyz errors on divergent changes — disambiguate with xyz/0, xyz/1. Fix:
jj abandon xyz/0
jj squash --from xyz/0 --into xyz/1
jj metaedit -r xyz/0 --update-change-id
git push Pushes Tracking Bookmarks
jj git push (no args) pushes tracking bookmarks in remote_bookmarks(remote=<remote>)..@. If nothing in that range is a tracking bookmark, nothing gets pushed. Common pattern:
jj bookmark create NAME -r @
jj git push --bookmark NAME
Operation Restore vs Undo vs Revert
jj undo / jj redo: undo/redo the last operation
jj op revert [OP]: create a new operation that inverts an earlier one (replaces the removed jj op undo)
jj op restore OP_ID: rewind the repo to any point in history
Before assuming changes are lost: check jj op log. Unsnapshotted edits are the one exception (see above).
See patterns/gotchas.md for extended gotchas (immutable commits, large files, conflict resolution, etc.)
Git Translation (Quick)
git status → jj st
git diff → jj diff
git commit -a → jj commit -m "msg"
git commit --amend → jj squash
git stash → jj new @-
git checkout -b → jj new main && jj bookmark create NAME
git rebase → jj rebase -s SRC -d DST
git log --graph → jj log
Help
jj help
jj help COMMAND
jj help -k revsets