重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/onevcat/skills --skill onevcat-jjjj 是一个与 Git 共存的版本控制工具。你在本地使用 jj;远程仓库仍然是标准的 Git。GitHub 和协作者看到的是普通的 git 提交和分支。
本技能教你如何正确且地道地使用 jj,特别是在智能体辅助的开发工作流中。
jj 围绕 变更 展开,而非分支。与 Git 的主要区别:
git add。jj new 即可开始新工作;之前的变更保持原状。jj edit 允许你跳转到任何变更并继续工作;后代变更会自动变基。工作副本本身就是一个变更。每个文件修改都会立即在当前变更中被跟踪。
在执行版本控制操作之前,检查仓库是否使用 jj:
# 如果 .jj/ 存在,使用 jj 命令 — 而非 git 命令
test -d .jj && echo "jj repo"
当仓库同时存在 .jj/ 和 .git/(共存模式)时,对于本地操作,应始终优先使用 jj 命令。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
在现有的 Git 仓库中初始化 jj(共存模式 — 保持 .git/ 与 .jj/ 并存):
jj git init --colocate
初始化后,你可能需要跟踪远程书签,以便 jj 了解远程分支:
jj bookmark track master@origin # 跟踪特定的远程分支
如果需要,jj 通常会提示你这一点。
jj log # 显示变更图 + 状态(替代 git log + git status)
jj diff # 显示当前变更与其父变更的差异
jj diff -r <change> # 显示特定变更的差异
jj log 的输出显示 @ 表示当前变更,以及简短的变更 ID(例如 kxryzmsp)。变更 ID 在变基操作中是稳定的 — 可以自由地将其用作引用。只要不产生歧义,你可以使用唯一前缀(例如 kx 代替 kxryzmsp)。
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 之后,修改文件会就地修正该变更。所有后代变更都会自动变基 — 在编辑祖先变更后,你永远不需要手动变基。
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 中,没有任何东西会真正丢失。
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 的书签。你在 jj log 中看到的 master(或 main)就是远程分支,通过书签访问。
在 jj git init --colocate 之后,或者当出现新的远程分支时,你可能需要 jj bookmark track <name>@<remote> 来告诉 jj 跟踪它。jj 会在需要时提示你。
推送工作流:
jj bookmark create <name> -r <change> — 给它一个 Git 分支名称jj git push — 推送到远程仓库(或使用 --bookmark <name> 仅推送一个)在放弃已推送的变更后进行清理: 当你 jj abandon 一个已将书签推送到远程的变更时,该书签会在本地被删除。使用 jj git push --deleted 将该删除操作同步到远程仓库。
jj workspace add ../workspace-name # 创建并行工作空间(类似 git worktree)
每个工作空间都有自己的目录,但共享底层的仓库存储。多个智能体可以在同一基础上,同时在独立的工作空间中工作,然后使用 jj new <change1> <change2> ... 合并结果。
这些模式利用了 jj 在智能体辅助开发中的优势。
只需 jj new 并开始。无需先添加、提交、推送或创建分支。之前的变更会自动保留。
jj new
jj describe -m "feat: implement avatar upload"
# 开始工作...
处理工作中的紧急任务:
jj new master # 从 master 分支出来进行紧急修复
# ... 进行修复 ...
jj describe -m "fix: critical auth bug"
jj edit <previous-change> # 跳回到你之前所在的位置
# ... 恢复之前的工作 ...
无需储藏,无需切换分支,无需恢复状态。
在产生一个大的变更后,将其拆分为逻辑部分:
jj split # 交互式:为第一个变更选择文件/代码块,其余部分归入第二个变更
jj split # 如果需要,再次拆分
如果拆分出错,使用 jj undo 并重试。
创建空变更作为计划,然后按顺序填充它们:
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"
然后逐个处理:
jj edit <first-change> # 跳转到第一个骨架变更
# ... 实现 ...
jj edit <next-change> # 跳转到下一个(之前的工作会自动变基后代变更)
# ... 实现 ...
每个变更的描述既作为提交信息,也作为验收标准。在继续之前,验证你的实现是否符合描述。
描述字段支持与 git 提交信息相同的格式:第一行是标题,空行,然后是正文。你可以使用 -m 在正文中编写详细的规范或提示。
jj undo # 撤销最后一次操作,无需询问
jj op log # 查看完整的操作历史记录,如果你需要回退更远
jj op restore <op-id> # 跳转到操作历史记录中的任何点
优先使用 jj undo,而不是尝试手动反转变更。它总是正确且安全的。
git add、git commit、git stash 或 git checkout。 改用 jj 的等效命令。jj edit 不可变的(已发布的)变更。 jj 会阻止此操作。如果你需要修复已发布历史中的某些内容,请使用 jj new <change> 创建一个后续变更。jj undo 或 jj op restore 从任何错误中恢复。| 任务 | jj 命令 |
|---|---|
| 在现有 git 仓库中初始化 | 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> |
本技能涵盖了最常见的操作。对于此处未涵盖的高级用法,请使用:
jj help # 列出所有命令
jj help <command> # 特定命令的详细帮助
jj help -k <keyword> # 按关键字搜索帮助
jj 拥有丰富的功能(修订集、模板、自定义别名、冲突解决等),你可以通过 jj help 探索并根据情况应用。官方文档位于 https://jj-vcs.github.io/jj/。
每周安装次数
54
仓库
GitHub 星标数
11
首次出现
8 天前
安全审计
安装于
codex51
gemini-cli49
opencode49
kimi-cli48
amp48
cline48
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 revolves around changes , not branches. Key differences from Git:
git add.jj new to start fresh work; previous changes stay where they are.jj edit lets you jump to any change and keep working; descendants auto-rebase.The working copy IS a change. Every file modification is instantly tracked in the current change.
Before performing version control operations, check if the repo uses jj:
# If .jj/ exists, use jj commands — not git commands
test -d .jj && echo "jj repo"
When a repo has both .jj/ and .git/ (colocated mode), always prefer jj commands for local operations.
To initialize jj in an existing Git repo (colocated mode — keeps .git/ alongside .jj/):
jj git init --colocate
After init, you may need to track remote bookmarks so jj knows about remote branches:
jj bookmark track master@origin # Track a specific remote branch
jj will usually hint you about this if it's needed.
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.
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.
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.
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:
jj bookmark create <name> -r <change> — give it a Git branch namejj 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.
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> ....
These patterns leverage jj's strengths for agent-assisted development.
Just jj new and begin. No need to add, commit, push, or create a branch first. The previous change is automatically preserved.
jj new
jj describe -m "feat: implement avatar upload"
# start working...
To handle an urgent task mid-work:
jj new master # Branch off master for the urgent fix
# ... do the fix ...
jj describe -m "fix: critical auth bug"
jj edit <previous-change> # Jump back to where you were
# ... resume previous work ...
No stash, no branch switching, no state to restore.
After producing a large change, split it into logical pieces:
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.
Create empty changes as a plan, then fill them in order:
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:
jj edit <first-change> # Jump to first skeleton change
# ... implement ...
jj edit <next-change> # Jump to next (previous work auto-rebases descendants)
# ... 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.
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.
git add, git commit, git stash, or git checkout in a jj repo. Use jj equivalents instead.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.jj undo or jj op restore to recover from any mistake.| Task | jj 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> |
This skill covers the most common operations. For advanced usage not covered here, use:
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/.
Weekly Installs
54
Repository
GitHub Stars
11
First Seen
8 days ago
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex51
gemini-cli49
opencode49
kimi-cli48
amp48
cline48
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
125,600 周安装
API 契约审计员 - 自动化审计 API 契约、服务边界与 DTO 模式的开发者工具
217 周安装
Linear 故事创建器:根据 IDEAL 计划自动生成用户故事,支持追加模式 | 项目管理自动化工具
216 周安装
Apple Liquid Glass 设计系统完全指南:实现、优化与专家审查 | axiom-liquid-glass
225 周安装
场景结构写作技巧:掌握场景-续场模型,提升小说叙事张力与节奏
216 周安装
故事质量门控工具:自动化代码质量检查与测试计划协调器 | 软件质量管理
218 周安装
Chrome DevTools MCP 服务器故障排查指南:配置修复与连接错误解决
223 周安装
| 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> |