Jujutsu (jj) VCS Command & Workflow Guide
Jujutsu is a Git-compatible VCS that uses a "working-copy-as-a-commit" model. There is no "index" or "staging area."
1. Core Concepts for the Agent
- •The Working Copy (@): Your current changes are always part of a commit. You don't "stage" files; you simply edit them and then "describe" the change or create a "new" one.
- •Change IDs vs. Commit IDs: Use Change IDs (shorter, stable) for most commands. Use Commit IDs only when specifically needed for low-level Git interop.
- •Operations: Every command creates an "operation" in a log. Use
jj op logandjj undoto navigate your own command history.
2. Orientation & Visibility (Critical)
Unlike Git, where you usually know which branch you are on, jj workflows often involve many "anonymous" changes.
- •The Map: Always use
jj log(orjj log -r "nodes()"for a dense view) to see where you are in the changeset graph. - •Your Location: Look for the
@symbol in the log output. This indicates the current working-copy commit. - •Inspect a Revision: Use
jj show <revision>to see the description and diff of a specific change without switching to it. - •State Check: Use
jj stfrequently. It summarizes the current Change ID, its parent, and any modified files. - •No Pager: When running these as an Agent, always append
--no-pagerto ensure the full context is captured in the interaction logs.
3. Common Git to Jujutsu Translation
| Git Command | Jujutsu Equivalent | Notes |
|---|---|---|
git status | jj st | Shows current change ID and modified files. |
git add | (N/A) | Files are tracked automatically once created. |
git commit -m "msg" | jj describe -m "msg" | Adds a message to the current open change. |
git commit --amend | jj describe -m "new msg" | Just re-describe the current change. |
git checkout -b branch | jj bookmark create <name> | "Bookmarks" are the equivalent of branches. |
git checkout <branch> | jj edit <bookmark> | Moves the working copy to that bookmark. |
git log | jj log | Shows a functional graph of changes. |
git show <commit> | jj show <revision> | Inspects description and diff of a revision. |
git diff | jj diff | Shows changes in the working copy. |
git push | jj git push | Explicitly pushes bookmarks to Git remotes. |
git reset --hard | jj abandon | Discards the current change and its edits. |
4. Bookmarks (Branches)
Bookmarks are pointers to specific revisions. Unlike Git branches, they do not move automatically unless you are at the "tip" of one.
- •Create:
jj bookmark create <name> -r <revision> - •Move:
jj bookmark set <name> -r <revision> - •Delete:
jj bookmark delete <name> - •List:
jj bookmark list - •Remote Tracking:
jj git push --bookmark <name>orjj git fetch.
5. Working with Stacked Changes
Jujutsu encourages "stacking" small, logical changes. Navigating these requires understanding the difference between moving the working copy and moving the edit focus.
- •
Move Up (Toward head):
jj next --editNote: Use
--editto move the actual working copy to the child. Without it, jj tries to create a new empty commit as a child of the descendant, which fails if the current working copy isn't empty. - •
Move Down (Toward root):
jj prev --edit - •
Edit Specific Revision:
jj edit <revision>(equivalent to checking out a specific commit in Git). - •
Create New Child:
jj new(creates a fresh, empty working copy on top of@). - •
Rebase Stack:
jj rebase -s <bottom_of_stack> -d <new_parent>. - •
View Stack:
jj log -r "ancestors(@) & ~ancestors(main)".
6. Advanced History & Revsets
Revsets are the "query language" of jj. Use -r to specify them.
Essential Selectors
- •
mine(): Changes authored by the current user. - •
empty(): Changes with no file modifications. - •
conflicts(): Changes containing merge conflicts. - •
root(): The virtual empty base of the repo. - •
heads(selection): The latest changes in a set. - •
bookmarks(): All changes associated with a bookmark.
Powerful Revset Examples
- •
jj log -r "mine() & ~empty()": Show my non-empty changes. - •
jj log -r "description(regex:'fix')": Search messages for "fix". - •
jj log -r "ancestors(@, 5)": Show the last 5 ancestors of the current work. - •
jj diff -r @--..@: Show the diff of the grandparent to the current change.
7. Operational Commands
- •Create New Work:
jj new(creates a new change on top of the current one). - •Merge Changes:
jj new revision1 revision2(creates a merge commit). - •Squash/Amend:
jj squash(moves changes from@into its parent@-). - •Splitting:
jj split(interactive tool to break one change into two).
8. Conflict Management
- •
jjallows commits to exist in a "conflicted" state. - •Conflict markers look like
<<<<<<<,=======, and>>>>>>>. - •To resolve: Edit the file to remove markers and keep desired code, then
jj describeor just continue working.
9. Constraints & Safety
- •No Git Commands: Never run
gitcommands inside a.jjrepo. - •Pager Handling: Always use
--no-pagerfor Agent-initiated commands. - •Snapshotting:
jjsnapshots the working copy on every command.
10. Troubleshooting
- •Divergence: If a change ID exists in two versions, use
jj rebaseorjj abandon. - •Push Failure:
jj git fetchfirst, thenjj rebaseyour work onto the remote bookmark. - •"Working copy must not have children": You likely tried
jj nextwithout--edit. If you want to move your focus to the next revision in the stack, usejj next --edit.