AgentSkillsCN

jj

使用 jj 版本控制系统。在执行所有版本控制操作时,包括提交、差异对比、日志查看、分支管理、变基、推送、拉取以及其他各类 VCS 任务,务必优先选用 jj,而非 Git。

SKILL.md
--- frontmatter
name: jj
description: Use the jj version control system. Always use this instead of git for all version control operations including commits, diffs, logs, branches, rebasing, pushing, pulling, and any other VCS tasks.

jj

Jujutsu is a Git-compatible VCS. The working copy is automatically snapshotted as a commit on every jj command — there is no staging area. All changes live in @ (the working-copy commit) until you finalize them.

Key Concepts

  • Change ID vs Commit ID — A change ID is a stable identifier that persists across rewrites. A commit ID (hash) changes whenever content is modified. Prefer change IDs when referring to revisions.
  • @ — The working-copy commit. @- is its parent.
  • No staging area — Files are tracked implicitly. New files are auto-tracked; use .gitignore to exclude files.
  • Automatic rebase — Rewriting a commit automatically rebases all its descendants.
  • First-class conflicts — Conflicts are recorded in commits and don't block operations. Resolve them later by editing the conflicted commit and squashing the fix.
  • Bookmarks — Named pointers to commits (equivalent to Git branches). They move automatically when the target commit is rewritten, but do not advance when you create new commits.

Common Commands

Viewing State

CommandPurpose
jj stShow working-copy status
jj logShow commit graph (defaults to non-remote commits)
jj log -r ::@Show ancestors of working copy
jj log -r 'all()'Show all commits
jj diffDiff of current revision (@)
jj diff -r <rev>Diff of a specific revision
jj diff --from A --to BDiff between two revisions
jj show <rev>Show a revision's changes and metadata
jj evologShow how a change evolved over time

Creating & Describing Changes

CommandPurpose
jj newFinalize @ and start a new empty change on top
jj new mainStart a new change from main
jj new A BCreate a merge commit with parents A and B
jj commit -m "msg"Describe @ and start a new change (= describe + new)
jj describe -m "msg"Set/edit the description of @
jj describe <rev> -m "msg"Set/edit the description of any revision

Squash

Squash moves changes from one commit into another.

CommandPurpose
jj squashMove all changes from @ into its parent (@-)
jj squash -iInteractively select which changes to move into parent
jj squash <paths>...Move only specific files into parent
jj squash --into <rev>Move changes from @ into an arbitrary ancestor
jj squash --from <rev>Move changes from <rev> into its parent
jj squash --from <rev> --into <rev>Move changes between arbitrary revisions
jj squash -i --from X --into YInteractively move selected changes between arbitrary revisions

Note: --from defaults to @, --into defaults to the parent of --from. The flags -r and --into cannot be combined.

Split

Split divides a commit into two or more sequential commits.

CommandPurpose
jj splitInteractively split @ — select changes for the first commit; the rest go into a second
jj split -r <rev>Split a revision other than @
jj split <paths>...Split by putting the listed files into the first commit

After splitting, you'll be prompted for descriptions for each resulting commit.

Editing History

CommandPurpose
jj edit <change-id>Check out a previous change for editing (becomes @)
jj edit @-Edit the parent of the current change
jj diffedit -r <rev>Edit a revision's diff without checking it out
jj abandonDiscard @ and rebase its descendants onto @-
jj restore <paths>...Restore files in @ from its parent
jj restore --from <rev> <paths>...Restore files from a specific revision
jj duplicate <rev>Copy a commit to a new change
jj revert -r <rev> -B @Create a reverse-patch of a revision before @

Navigation

CommandPurpose
jj next --editMove to the next (child) change
jj prev --editMove to the previous (parent) change

Rebasing

CommandPurpose
jj rebase -s <src> -o <onto>Rebase <src> and descendants onto <onto>
jj rebase -b <rev> -o <onto>Rebase the branch containing <rev> onto <onto>
jj rebase -r <rev> -o <onto>Rebase only <rev> (re-parents descendants)
jj rebase -r <rev> --before <target>Insert <rev> before <target>
jj rebase -r <rev> --after <target>Insert <rev> after <target>

Note: -d/--destination is a legacy alias for -o/--onto.

Bookmarks (Branches)

CommandPurpose
jj bookmark list / jj b lList bookmarks
jj bookmark create <name> -r <rev> / jj b c <name>Create bookmark
jj bookmark move <name> --to <rev> / jj b m <name> -t <rev>Move bookmark
jj bookmark move <name> --to <rev> --allow-backwardsMove bookmark backwards
jj bookmark delete <name>Delete bookmark
jj bookmark track <name>@<remote>Track a remote bookmark

Git Integration

CommandPurpose
jj git initInitialize jj repo with git backend
jj git clone <url> <dir>Clone a git repository
jj git fetchFetch from remote (updates tracked bookmarks)
jj git pushPush tracked bookmarks to remote
jj git push --bookmark <name>Push a specific bookmark
jj git push --change <rev>Push a change (auto-creates bookmark)
jj git push --allPush all bookmarks

Conflict Resolution

Conflicts are stored in commits and don't block operations.

  1. jj new <conflicted-rev> — create a child to work in
  2. Edit files to resolve conflict markers (<<<<<<< / %%%%%%% / +++++++ / >>>>>>>)
  3. jj squash — fold the resolution back into the conflicted commit

Or use jj resolve to open a merge tool.

Undo & Operations

CommandPurpose
jj undoUndo the last operation
jj op logShow operation history
jj op restore <op-id>Restore repo to a previous operation state

GitHub PR Workflow

bash
jj new main                        # start from main
# ... make changes ...
jj commit -m "feat: add feature"   # finalize with message
jj git push --change @-            # push with auto-generated bookmark

To update a PR after review:

bash
jj edit <change-id>                # go back to the PR commit
# ... make changes ...
jj new                             # done editing, start fresh change
jj git push --bookmark <name>      # push updated bookmark

Revset Quick Reference

Use -r flag on most commands to select revisions.

ExpressionMeaning
@Working copy
@-Parent of working copy
@--Grandparent
x-Parents of x
x+Children of x
::xAncestors of x (inclusive)
x::Descendants of x (inclusive)
x..yCommits in y but not in x (like git x..y)
x | yUnion
x & yIntersection
~xNegation
bookmarks()All bookmarked commits
remote_bookmarks()All remote-tracked commits
heads(x)Commits in x with no descendants in x
roots(x)Commits in x with no ancestors in x
description(pattern)Commits matching description
author(pattern)Commits matching author
empty()Empty commits
conflicts()Commits with conflicts
files(pattern)Commits touching files matching pattern

String patterns: exact:, glob: (default), regex:, substring:. Append -i for case-insensitive (e.g. glob-i:"fix*").

For full revset docs: jj help -k revsets