onevcat-jj

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

jj (Jujutsu) — Version Control for Agent Workflows

jj(Jujutsu)—— 适用于 Agent 工作流的版本控制工具

jj is a version control tool that coexists with Git. You use jj locally; the remote is still standard Git. GitHub and collaborators see ordinary git commits and branches.
This skill teaches you how to use jj correctly and idiomatically, especially in agent-assisted development workflows.
jj 是一款可与 Git 共存的版本控制工具。你可以在本地使用 jj,而远程仓库仍采用标准 Git 架构。GitHub 平台及协作者看到的将是普通的 Git 提交与分支。
本技能将教你如何正确、地道地使用 jj,尤其是在 Agent 辅助的开发工作流中。

Core Mental Model

核心思维模型

jj revolves around changes, not branches. Key differences from Git:
  • No staging area. File modifications are automatically part of the current change. There is no
    git add
    .
  • No stash. Just
    jj new
    to start fresh work; previous changes stay where they are.
  • No detached HEAD.
    jj edit
    lets you jump to any change and keep working; descendants auto-rebase.
  • Branches are called bookmarks and are only needed when pushing to a remote.
The working copy IS a change. Every file modification is instantly tracked in the current change.
jj 围绕**变更(changes)**而非分支展开。与 Git 的主要区别:
  • 无暂存区:文件修改会自动成为当前变更的一部分,无需执行
    git add
    命令。
  • 无暂存(stash)功能:只需执行
    jj new
    即可开始新的工作,之前的变更会保留在原位。
  • 无游离 HEAD 状态
    jj edit
    允许你切换到任意变更并继续工作,其后续变更会自动完成变基。
  • 分支被称为bookmark(书签):仅在推送到远程仓库时才需要使用。
工作区本身就是一个变更。所有文件修改都会立即被追踪到当前变更中。

Detecting a jj Repo

检测 jj 仓库

Before performing version control operations, check if the repo uses jj:
bash
undefined
执行版本控制操作前,请先检查仓库是否使用 jj:
bash
undefined

If .jj/ exists, use jj commands — not git commands

若 .jj/ 目录存在,请使用 jj 命令而非 Git 命令

test -d .jj && echo "jj repo"

When a repo has both `.jj/` and `.git/` (colocated mode), always prefer jj commands for local operations.
test -d .jj && echo "jj repo"

当仓库同时存在 `.jj/` 和 `.git/` 目录(共存模式)时,本地操作请优先使用 jj 命令。

Setup

初始化配置

To initialize jj in an existing Git repo (colocated mode — keeps
.git/
alongside
.jj/
):
bash
jj git init --colocate
After init, you may need to track remote bookmarks so jj knows about remote branches:
bash
jj bookmark track master@origin        # Track a specific remote branch
jj will usually hint you about this if it's needed.
在已有的 Git 仓库中初始化 jj(共存模式 —— 保留 .git/ 目录与 .jj/ 目录并存):
bash
jj git init --colocate
初始化完成后,你可能需要追踪远程书签,让 jj 知晓远程分支的存在:
bash
jj bookmark track master@origin        # 追踪指定的远程分支
若有需要,jj 通常会主动提示你执行该操作。

Essential Commands

核心命令

Inspect State

查看仓库状态

bash
jj log                    # Show change graph + status (replaces git log + git status)
jj diff                   # Show diff of current change vs parent
jj diff -r <change>       # Show diff of a specific change
jj log
output shows
@
for the current change and short Change IDs (e.g.,
kxryzmsp
). Change IDs are stable across rebases — use them freely as references. You can use unique prefixes (e.g.,
kx
instead of
kxryzmsp
) as long as they are unambiguous.
bash
jj log                    # 显示变更图谱及状态(替代 git log + git status)
jj diff                   # 显示当前变更与父变更的差异
jj diff -r <change>       # 显示指定变更的差异
jj log
的输出中,
@
代表当前变更,同时会显示简短的变更 ID(例如:
kxryzmsp
)。变更 ID 在变基后仍保持稳定,你可以放心地将其作为引用。只要前缀唯一,你也可以使用缩写(例如用
kx
代替
kxryzmsp
)。

Work on Changes

处理变更

bash
jj describe -m "feat: add auth module"   # Set/update description of current change
jj describe -r <change> -m "new msg"     # Update description of any change
jj new                                    # Finish current change, start a new empty one
jj new <change>                           # Start new work branching from a specific change
jj commit -m "feat: ..."                  # Shorthand: describe current + start new (equivalent to describe + new)
jj edit <change>                          # Jump to an existing change and continue editing it
jj abandon                                # Discard the current change entirely
jj abandon <change>                       # Discard a specific change
jj new
is your primary "next task" command.
It seals the current change and gives you a fresh workspace. No add, no commit ceremony.
jj abandon
discards a change completely. The change's modifications are absorbed into its parent. Use it to clean up empty changes, throw away unwanted work, or remove a change from a chain.
jj edit
is safe:
if the target change is immutable (already pushed to remote), jj will refuse with an error. You do not need to check this yourself.
After
jj edit
, modifying files amends that change in place. All descendant changes auto-rebase — you never need to manually rebase after editing an ancestor.
bash
jj describe -m "feat: add auth module"   # 设置或更新当前变更的描述
jj describe -r <change> -m "new msg"     # 更新指定变更的描述
jj new                                    # 完成当前变更,创建一个新的空变更
jj new <change>                           # 基于指定变更创建新的工作分支
jj commit -m "feat: ..."                  # 快捷操作:描述当前变更并创建新变更(等效于 describe + new)
jj edit <change>                          # 切换到已有变更并继续编辑
jj abandon                                # 完全丢弃当前变更
jj abandon <change>                       # 丢弃指定变更
jj new
是你开启“下一项任务”的核心命令
。它会封存当前变更,并为你提供一个全新的工作区。无需执行添加、提交等繁琐步骤。
jj abandon
会完全丢弃一个变更,该变更的修改会被合并到其父变更中。你可以用它来清理空变更、丢弃不需要的工作,或从变更链中移除某个变更。
jj edit
是安全的
:如果目标变更为不可变状态(已推送到远程仓库),jj 会直接返回错误阻止操作,你无需自行检查。
执行
jj edit
后,修改文件会直接在该变更上进行追加。所有后续变更会自动完成变基——你永远无需在编辑祖先变更后手动执行变基操作。

Reorganize History

重构历史

bash
jj split                                 # Interactively split current change into two (or more)
jj split -r <change>                     # Split a specific change
jj rebase -s <source> -d <destination>   # Move a change (and its descendants) to a new parent
jj rebase -d <destination>               # Rebase current branch onto destination
jj undo                                  # Undo the last jj operation (any operation)
jj op log                                # View operation-level history
jj op restore <operation-id>             # Restore repo to any previous operation state
jj split
opens an interactive editor by default (when no filesets are given). Select which files/hunks belong to the first change; the rest automatically become the second. Repeat to split further.
jj undo
undoes the last operation regardless of what it was — rebase, split, describe, anything. It is always safe. Nothing is ever truly lost in jj.
bash
jj split                                 # 交互式地将当前变更拆分为两个(或多个)变更
jj split -r <change>                     # 拆分指定变更
jj rebase -s <source> -d <destination>   # 将一个变更(及其后续变更)移动到新的父变更
jj rebase -d <destination>               # 将当前分支变基到目标变更
jj undo                                  # 撤销上一次 jj 操作(任意操作均可撤销)
jj op log                                # 查看操作级别的历史记录
jj op restore <operation-id>             # 将仓库恢复到任意历史操作状态
默认情况下(未指定文件集时),
jj split
会打开交互式编辑器。你可以选择哪些文件/代码块属于第一个变更,剩余内容会自动成为第二个变更。重复执行可进一步拆分。
jj undo
可以撤销上一次操作,无论操作类型是变基、拆分、描述还是其他。它始终是安全的,jj 中没有任何内容会被真正永久丢失。

Remote Interaction (Git Bridge)

远程交互(Git 桥接)

bash
jj git fetch                             # Fetch from remote (like git fetch)
jj rebase -d master                      # Rebase current work onto latest master
jj bookmark track master@origin          # Track a remote branch (needed after init or for new remotes)
jj bookmark create my-feature -r @       # Create a bookmark (= git branch) pointing at current change
jj bookmark create my-feature -r <chg>   # Create a bookmark pointing at a specific change
jj bookmark set my-feature -r <change>   # Move an existing bookmark to a different change
jj git push                              # Push all changed bookmarks to remote
jj git push --bookmark my-feature        # Push only a specific bookmark
jj git push --deleted                    # Push bookmark deletions to remote (after jj abandon)
Remote Git branches are automatically mapped to jj bookmarks on fetch. The
master
(or
main
) you see in
jj log
IS the remote branch, accessed via bookmark.
After
jj git init --colocate
or when a new remote branch appears, you may need
jj bookmark track <name>@<remote>
to tell jj to follow it. jj will hint you when this is needed.
Workflow for pushing:
  1. Finish your work (describe the change)
  2. jj bookmark create <name> -r <change>
    — give it a Git branch name
  3. jj git push
    — push to remote (or
    --bookmark <name>
    for just one)
Cleanup after abandoning a pushed change: When you
jj abandon
a change that had a bookmark pushed to remote, the bookmark is deleted locally. Use
jj git push --deleted
to sync that deletion to the remote.
bash
jj git fetch                             # 从远程仓库拉取代码(类似 git fetch)
jj rebase -d master                      # 将当前工作变基到最新的 master 分支
jj bookmark track master@origin          # 追踪远程分支(初始化后或新增远程分支时需要执行)
jj bookmark create my-feature -r @       # 创建一个书签(等效于 Git 分支)指向当前变更
jj bookmark create my-feature -r <chg>   # 创建一个书签指向指定变更
jj bookmark set my-feature -r <change>   # 将已有书签移动到另一个变更
jj git push                              # 将所有已修改的书签推送到远程仓库
jj git push --bookmark my-feature        # 仅推送指定的书签
jj git push --deleted                    # 将书签的删除操作推送到远程仓库(执行 jj abandon 后需要)
拉取远程代码时,Git 远程分支会自动映射为 jj 的bookmark(书签)。你在
jj log
中看到的
master
(或
main
)就是远程分支,通过书签访问。
执行
jj git init --colocate
后或出现新的远程分支时,你可能需要执行
jj bookmark track <name>@<remote>
让 jj 追踪该分支。当需要执行此操作时,jj 会主动提示你。
推送工作流:
  1. 完成工作(描述变更)
  2. jj bookmark create <name> -r <change>
    —— 为其设置一个 Git 分支名称
  3. jj git push
    —— 推送到远程仓库(或使用
    --bookmark <name>
    仅推送指定分支)
丢弃已推送变更后的清理: 当你使用
jj abandon
丢弃一个已推送到远程仓库的变更时,对应的书签会在本地被删除。执行
jj git push --deleted
可将该删除操作同步到远程仓库。

Parallel Workspaces

并行工作区

bash
jj workspace add ../workspace-name       # Create a parallel workspace (like git worktree)
Each workspace gets its own directory but shares the underlying repository store. Multiple agents can work in separate workspaces simultaneously from the same base, then merge results with
jj new <change1> <change2> ...
.
bash
jj workspace add ../workspace-name       # 创建并行工作区(类似 git worktree)
每个工作区都有独立的目录,但共享底层的仓库存储。多个 Agent 可以同时在同一仓库的不同并行工作区中工作,之后通过
jj new <change1> <change2> ...
合并结果。

Agent Workflow Patterns

Agent 工作流模式

These patterns leverage jj's strengths for agent-assisted development.
以下模式充分利用了 jj 的特性,适用于 Agent 辅助的开发工作。

Pattern 1: Start Next Task

模式 1:开启新任务

Just
jj new
and begin. No need to add, commit, push, or create a branch first. The previous change is automatically preserved.
bash
jj new
jj describe -m "feat: implement avatar upload"
只需执行
jj new
即可开始工作。无需先执行添加、提交、推送或创建分支等操作,之前的变更会被自动保留。
bash
jj new
jj describe -m "feat: implement avatar upload"

start working...

开始工作...

undefined
undefined

Pattern 2: Interrupt and Resume

模式 2:中断与恢复

To handle an urgent task mid-work:
bash
jj new master            # Branch off master for the urgent fix
在工作中途处理紧急任务:
bash
jj new master            # 基于 master 分支创建新变更以处理紧急修复

... do the fix ...

... 完成修复 ...

jj describe -m "fix: critical auth bug" jj edit <previous-change> # Jump back to where you were
jj describe -m "fix: critical auth bug" jj edit <previous-change> # 切换回之前的变更继续工作

... resume previous work ...

... 恢复之前的工作 ...


No stash, no branch switching, no state to restore.

无需暂存、切换分支或恢复状态。

Pattern 3: Split After the Fact

模式 3:事后拆分

After producing a large change, split it into logical pieces:
bash
jj split                 # Interactive: pick files/hunks for first change, rest goes to second
jj split                 # Split again if needed
If a split goes wrong,
jj undo
and try again.
完成一个大型变更后,将其拆分为多个逻辑独立的变更:
bash
jj split                 # 交互式操作:选择文件/代码块属于第一个变更,剩余内容自动成为第二个变更
jj split                 # 若需要可继续拆分
如果拆分操作出错,执行
jj undo
后重新尝试即可。

Pattern 4: Skeleton Planning (Recommended for Complex Tasks)

模式 4:骨架规划(推荐用于复杂任务)

Create empty changes as a plan, then fill them in order:
bash
jj commit -m "refactor: extract auth module"
jj commit -m "feat: add token refresh logic"
jj commit -m "test: update auth tests"
jj commit -m "docs: update API documentation"
Then work through them:
bash
jj edit <first-change>   # Jump to first skeleton change
先创建空变更作为计划,再按顺序填充内容:
bash
jj commit -m "refactor: extract auth module"
jj commit -m "feat: add token refresh logic"
jj commit -m "test: update auth tests"
jj commit -m "docs: update API documentation"
然后逐个实现:
bash
jj edit <first-change>   # 切换到第一个骨架变更

... implement ...

... 实现内容 ...

jj edit <next-change> # Jump to next (previous work auto-rebases descendants)
jj edit <next-change> # 切换到下一个变更(之前的工作会自动为后续变更完成变基)

... implement ...

... 实现内容 ...


Each change's description serves as both the commit message and the acceptance criteria. Verify your implementation matches the description before moving on.

The description field supports the same format as git commit messages: first line is the title, blank line, then body. You can write detailed specs or prompts in the body with `-m`.

每个变更的描述既作为提交信息,也作为验收标准。在切换到下一个变更前,请确保你的实现与描述一致。

描述字段支持与 Git 提交信息相同的格式:第一行为标题,空行后为正文。你可以使用 `-m` 参数在正文中编写详细的规格说明或提示信息。

Pattern 5: Undo and Recover

模式 5:撤销与恢复

bash
jj undo                  # Undo last operation, no questions asked
jj op log                # See full operation history if you need to go further back
jj op restore <op-id>    # Jump to any point in operation history
Prefer
jj undo
over trying to manually reverse changes. It is always correct and safe.
bash
jj undo                  # 撤销上一次操作,无需额外确认
jj op log                # 查看完整的操作历史,若需要恢复到更早的状态
jj op restore <op-id>    # 切换到任意操作历史状态
优先使用
jj undo
而非手动撤销变更,它始终是正确且安全的。

Common Mistakes to Avoid

常见错误规避

  • Do not use
    git add
    ,
    git commit
    ,
    git stash
    , or
    git checkout
    in a jj repo.
    Use jj equivalents instead.
  • Do not try to
    jj edit
    an immutable (published) change
    without good reason. jj will block this. If you need to fix something in published history, use
    jj new <change>
    to create a follow-up change instead.
  • Do not create bookmarks for local-only work. Bookmarks are only needed when pushing to remote. Local work is tracked by Change IDs.
  • Do not worry about "losing" changes. jj's operation log preserves everything. Use
    jj undo
    or
    jj op restore
    to recover from any mistake.
  • 请勿在 jj 仓库中使用
    git add
    git commit
    git stash
    git checkout
    命令
    ,请使用对应的 jj 命令替代。
  • 请勿尝试
    jj edit
    不可变(已发布)的变更
    ,除非有充分理由。jj 会阻止此操作。若需要修复已发布历史中的内容,请使用
    jj new <change>
    创建一个后续变更。
  • 请勿为仅本地的工作创建书签,书签仅在推送到远程仓库时才需要使用。本地工作通过变更 ID 追踪。
  • 无需担心“丢失”变更,jj 的操作日志会保留所有内容。使用
    jj undo
    jj op restore
    可从任何错误中恢复。

Quick Reference

快速参考

Taskjj command
Initialize in existing git repo
jj git init --colocate
See what's going on
jj log
Describe current change
jj describe -m "..."
Start next task
jj new
Branch from specific change
jj new <change>
Edit an older change
jj edit <change>
Discard a change
jj abandon
/
jj abandon <change>
Split a change
jj split
Undo anything
jj undo
Fetch remote
jj git fetch
Track a remote branch
jj bookmark track <name>@<remote>
Rebase onto master
jj rebase -d master
Create bookmark for push
jj bookmark create <name> -r @
Move existing bookmark
jj bookmark set <name> -r <change>
Push to remote
jj git push
Push specific bookmark
jj git push --bookmark <name>
Push bookmark deletions
jj git push --deleted
Merge multiple changes
jj new <chg1> <chg2> ...
Parallel workspace
jj workspace add <path>
任务jj 命令
在已有 Git 仓库中初始化 jj
jj git init --colocate
查看仓库状态
jj log
描述当前变更
jj describe -m "..."
开启新任务
jj new
基于指定变更创建分支
jj new <change>
编辑历史变更
jj edit <change>
丢弃变更
jj abandon
/
jj abandon <change>
拆分变更
jj split
撤销任意操作
jj undo
拉取远程代码
jj git fetch
追踪远程分支
jj bookmark track <name>@<remote>
变基到 master 分支
jj rebase -d master
创建用于推送的书签
jj bookmark create <name> -r @
移动已有书签
jj bookmark set <name> -r <change>
推送到远程仓库
jj git push
推送指定书签
jj git push --bookmark <name>
推送书签删除操作
jj git push --deleted
合并多个变更
jj new <chg1> <chg2> ...
创建并行工作区
jj workspace add <path>

Beyond This Skill

拓展学习

This skill covers the most common operations. For advanced usage not covered here, use:
bash
jj help                  # List all commands
jj help <command>        # Detailed help for a specific command
jj help -k <keyword>     # Search help by keyword
jj has rich functionality (revsets, templates, custom aliases, conflict resolution, etc.) that you can explore via
jj help
and apply based on the situation. The official documentation is at https://jj-vcs.github.io/jj/.
本技能覆盖了最常用的操作。对于未涵盖的高级用法,请使用以下命令查询:
bash
jj help                  # 列出所有命令
jj help <command>        # 查看指定命令的详细帮助
jj help -k <keyword>     # 按关键词搜索帮助内容
jj 拥有丰富的功能(变更集、模板、自定义别名、冲突解决等),你可以通过
jj help
探索并根据实际场景使用。官方文档地址为:https://jj-vcs.github.io/jj/。