Jujutsu
Git-compatible VCS focused on concurrent development and ease of use.
⚠️ Not Git! Jujutsu syntax differs from Git:
-
Parent: @- not @~1 or @^
-
Grandparent: @-- not @~2
-
Child: @+ not @~-1
-
Use jj log not jj changes
Key Commands
Command Description
jj st
Show working copy status
jj log
Show change log
jj diff
Show changes in working copy
jj new
Create new change
jj desc
Edit change description
jj squash
Move changes to parent
jj split
Split current change
jj rebase -s src -d dest
Rebase changes
jj absorb
Move changes into stack of mutable revisions
jj bisect
Find bad revision by bisection
jj fix
Update files with formatting fixes
jj sign
Cryptographically sign a revision
jj metaedit
Modify metadata without changing content
Project Setup
jj git init # Init in existing git repo jj git init --colocate # Side-by-side with git
Basic Workflow
jj new # Create new change jj desc -m "feat: add feature" # Set description jj log # View history jj edit change-id # Switch to change jj new --before @ # Time travel (create before current) jj edit @- # Go to parent
Time Travel
jj edit change-id # Switch to specific change jj next --edit # Next child change jj edit @- # Parent change jj new --before @ -m msg # Insert before current
Merging & Rebasing
jj new x yz -m msg # Merge changes jj rebase -s src -d dest # Rebase source onto dest jj abandon # Delete current change
Conflicts
jj resolve # Interactive conflict resolution
Edit files, then continue
Revset Syntax
Parent/child operators:
Syntax Meaning Example
@-
Parent of @ jj diff -r @-
@--
Grandparent jj log -r @--
x-
Parent of x jj diff -r abc123-
@+
Child of @ jj log -r @+
x::y
x to y inclusive jj log -r main::@
x..y
x to y exclusive jj log -r main..@
x|y
Union (or) jj log -r 'a | b'
⚠️ Common mistakes:
-
❌ @~1 → ✅ @- (parent)
-
❌ @^ → ✅ @- (parent)
-
❌ @~-1 → ✅ @+ (child)
-
❌ jj changes → ✅ jj log or jj diff
-
❌ a,b,c → ✅ a | b | c (union uses pipe, not comma)
Functions:
jj log -r 'heads(all())' # All heads jj log -r 'remote_bookmarks()..' # Not on remote jj log -r 'author(name)' # By author jj log -r 'description(regex)' # By description jj log -r 'mine()' # My commits jj log -r 'committer_date(after:"7 days ago")' # Recent commits jj log -r 'mine() & committer_date(after:"yesterday")' # My recent
Templates
jj log -T 'commit_id ++ "\n" ++ description'
Git Interop
jj bookmark create main -r @ # Create bookmark jj git push --bookmark main # Push bookmark jj git fetch # Fetch from remote jj bookmark track main@origin # Track remote
Advanced Commands
jj absorb # Auto-move changes to relevant commits in stack jj bisect start # Start bisection jj bisect good # Mark current as good jj bisect bad # Mark current as bad jj fix # Run configured formatters on files jj sign -r @ # Sign current revision jj metaedit -r @ -m "new message" # Edit metadata only
Tips
-
No staging: changes are immediate
-
Use conventional commits: type(scope): desc
-
jj undo to revert operations
-
jj op log to see operation history
-
Bookmarks are like branches
-
jj absorb is powerful for fixing up commits in a stack
Related Skills
-
gh: GitHub CLI for PRs and issues
-
review: Code review before committing