| name | jj |
| description | Use for ALL version control operations in projects. Handles commits, history, branches (bookmarks), remotes, diffs, conflict resolution, workspaces, and repository management using the jujutsu (jj) CLI. Triggers on: commit, branch, push, pull, merge, diff, log, history, undo, stash, rebase, squash, worktree, workspace, or any VCS/source control request.
|
Jujutsu (jj) Version Control Skill
Use jj for all version control operations. Never fall back to raw git commands
for repository operations — jj manages the underlying git repo transparently.
Core Concepts
Changes vs Commits
- A change is the primary unit in jj (like a git commit, but mutable)
- Changes have a stable change ID (e.g.
qpvuntsm) that persists even after rebasing
- Changes also have a commit ID (content hash) that changes when content changes
- Use the shortest unique prefix of a change ID in commands (e.g.
qp instead of full ID)
Working Copy (@)
- The current working copy is always a change, denoted by
@ in logs
- jj auto-snapshots the working copy at the start of every command — no
git add needed
- All files are tracked by default; use
.gitignore to exclude files
Revsets
A functional query language for selecting commits:
@ # current working copy
@- # parent of working copy
trunk # bookmark named "trunk"
main # bookmark named "main"
trunk..@ # all changes from trunk up to @
roots(trunk..@) # root changes in that range (no parent in the set)
heads(trunk..@) # head changes in that range (no child in the set)
all:X # prefix for commands expecting multiple revisions
Bookmarks (Branches)
- Bookmarks are named pointers to commits (equivalent to git branches)
- They do not move automatically — must be explicitly updated
- Remote tracking:
main@origin tracks the remote bookmark
Command Reference
Status & Inspection
jj status
jj log
jj log --limit 10
jj log -r 'all()'
jj log -r trunk..@
jj show
jj show <rev>
jj diff
jj diff -r <rev>
jj diff --from <rev> --to <rev>
Creating & Editing Changes
jj new
jj new <parent>
jj new --no-edit <parent>
jj describe -m "message"
jj describe -r <rev> -m "message"
jj commit -m "message"
Moving & Reorganizing
jj rebase -s <source> -d <destination>
jj rebase -s 'all:roots(trunk..@)' -d trunk
jj squash
jj squash -r <rev>
jj squash --from <rev> --into <rev>
jj split
jj absorb
Undo & Abandon
jj undo
jj redo
jj abandon <rev>
jj op log
jj op undo <op>
Bookmarks (Branches)
jj bookmark list
jj bookmark set <name>
jj bookmark set <name> -r <rev>
jj bookmark delete <name>
jj bookmark rename <old> <new>
jj bookmark track <name>@<remote>
Working with Remotes (Git)
jj git clone <url>
jj git fetch
jj git fetch --remote origin
jj git push
jj git push --bookmark <name>
jj git push --change @
jj git remote add <name> <url>
jj git remote list
Conflict Resolution
jj resolve
jj resolve --list
jj status
File Operations
jj restore <file>
jj restore --from <rev> <file>
jj file list
Workspaces
Workspaces are jj's alternative to git worktrees — multiple working copies sharing the same repo.
Each workspace has its own @ (working-copy commit) and can be on a different change.
Always create workspaces as siblings of the project at ../<feature-name>.
jj workspace list
jj workspace add ../<feature-name>
jj workspace add ../<feature-name> -r <rev>
jj workspace add ../<feature-name> --name <name>
cd ../<feature-name>
jj status
jj log
jj workspace forget <name>
jj workspace update-stale
Typical workspace workflow:
jj workspace add ../feature-x
cd ../feature-x
jj describe -m "wip: feature x"
jj new
cd <PROJECT_DIR>
jj status
cd <PROJECT_DIR>
jj workspace forget feature-x
rm -rf ../feature-x
Common Workflows
Starting a New Project
jj git init --colocate
jj git clone https://github.com/user/repo
Daily Work Loop
jj status
jj describe -m "add feature X"
jj new
jj log
Committing Work
jj describe -m "implement login"
jj new
jj commit -m "implement login"
Working on a Feature (with bookmarks)
jj bookmark set feature-x
jj describe -m "start feature X"
jj new
jj describe -m "finish feature X"
jj bookmark set feature-x
jj git push --bookmark feature-x
Stacked Changes / Pull Requests
jj excels at stacked diffs. Each change is independently addressable:
jj describe -m "refactor: extract helper"
jj new
jj describe -m "feat: use helper in main"
jj new
jj describe -m "test: add tests for helper"
jj log -r trunk..@
jj git fetch
jj rebase -s 'all:roots(trunk..@)' -d trunk@origin
Undoing Mistakes
jj undo
jj op log
jj op undo <op-id>
jj abandon <change-id>
Squashing/Cleaning Up Before Push
jj squash
jj squash -i
jj squash --from <child> --into <parent>
Syncing with Remote
jj git fetch
jj rebase -s 'all:roots(main@origin..@)' -d main@origin
jj git push --change @
Key Differences from Git
| Operation | Git | jj |
|---|
| Stage files | git add | Not needed — auto-snapshot |
| Commit | git commit -m "..." | jj commit -m "..." or jj describe + jj new |
| Amend last commit | git commit --amend | jj describe (just edit the current change) |
| Create branch | git checkout -b name | jj bookmark set name + jj new |
| Switch branch | git checkout name | jj edit name or jj new name |
| Undo commit | git reset HEAD~ | jj undo |
| View log | git log | jj log |
| Stash | git stash | Not needed — just jj new and come back |
| Interactive rebase | git rebase -i | jj squash, jj split, jj rebase |
| Cherry-pick | git cherry-pick | jj duplicate -r <rev> + rebase |
| Push branch | git push origin name | jj git push --bookmark name |
| Worktree | git worktree add | jj workspace add ../<name> |
Safety Notes
jj undo is always safe — jj records every operation and any state can be recovered
- Conflicts are stored in commits — rebases always succeed; conflicts persist in the change and can be resolved later
- No staging area — the working copy IS the current change;
jj new when ready to start the next one
- Do not mix raw
git commands with jj in the same repo — use jj git import/jj git export if you must interop