在Jujutsu仓库的日常开发里,常遇到这样的尴尬:想把手头工作区中的多处修改拆成几个语义清晰的提交,但jj split强制你一步步交互选择。对于习惯用脚本串联研发流程、或在CI中自动拆分变更的开发者,这种交互模式就成了效率瓶颈。新工具jjc正是为此而生——它把“代码块级”的操作完全非交互化,让拆分、丢弃、归并修改都变成可写入脚本的确定性指令。

jjc 被设计为jj split交互模式的脚本化替代品,运行前提是你的环境已安装 Jujutsu v0.41.0 或更高版本。安装方式与众多 Rust 生态工具一致,通过 cargo 直接拉取 Git 仓库:

cargo install --git https://tangled.sh/akashina.tngl.sh/jjc

如果克隆了源码到本地,也可以从本地路径执行cargo install --path .。两种方式都会将 jjc 编译为独立二进制,随后便可在终端直接调用

工具的核心能力由四个子命令承接:hunks(查看代码块)、pick(挑选块形成新提交)、drop(丢弃块回退到父版本)、fold(将块压缩进其他修订)。所有写命令都使用统一的代码块选择器语法——先用jjc hunks查看可用的块标识符,再把标识符传给后续操作。

洞察仓库里的每一个“块” —— jjc hunks

在动手拆分之前,第一步永远是理清当前有多少个可独立操作的修改部分。直接输入jjc hunks,就会列出@(当前修订)中包含的全部变更片断。如果想检查某个特定修订,比如main分支,可以用-r参数:

jjc hunks -r main

若要深入观察某一个代码块,直接在其 ID 或唯一前缀后面跟上即可,例如jjc hunks abc123。默认输出会为每个块展示一个简洁的变化预览(最多4行被修改的行):

a1b[2c3d4e5f6] src/main.rs (+3 -1)+ println!("new line");- old_call();f09[8a7b6c5d4e] src/lib.rs (+1 -0)+use std::io;

其中a1b[2c3d4e5f6]就是该代码块的唯一标识符,方括号内的部分高亮显示,这种风格与jj log的输出一致,a1b即为最短唯一前缀。当你需要更丰富的上下文时,可以追加--full标志。此时输出不仅会补全代码行所在的行号,还会在块内部存在多个“变化原子”时,把它们拆解为带编号的子块:

a1b[2c3d4e5f6] src/main.rs (+3 -1)1: fn main() {2:+ println!("new line");3:- old_call();a1b[2c3d4e5f6]#1 @2 a1b[2c3d4e5f6]#2 @3

你会看到多了形如a1b[2c3d4e5f6]#1#2的子标识符,它们分别代表这个大块内部的独立修改原子——这在后续pick时非常有用,允许你只提取“修复了一处偏移错误”而留下“调整了注释”的修改。

如果想追溯每一行代码最初是由哪次提交引入的,可以加上--blame选项,它会像 git blame 那样在每一行旁标注原始提交散列值,让你在计划拆分时能快速判断某个修改是否属于本次变更范围。

精准拆分,从块到新提交 —— jjc pick

选好要提取的代码段后,jjc pick可以直接为你创建新提交。例如,将标识符为a1b的整个块移入新提交并写上说明:

jjc pick a1b -m "extract logging"

如果只想提取该块内的某一个变更原子,比如第2个,使用子标识符a1b#2

jjc pick a1b#2 -m "fix off-by-one"

你甚至能按目标行范围提取,或者一次指定多个标识符,从特定修订中挑出想要的片段。新提交会包含这些选中的修改,然后源修订被重写到新提交之上,效果和jj split一样,但全程无需交互。

直接丢弃块 —— jjc drop

想把某些修改干脆扔掉也很简单。用jjc drop指定要回退的块,该修订会被原地改写,选中的代码片段退回到父版本内容:

jjc drop a1b          # 丢弃一个块jjc drop a1b c3d      # 丢弃多个块

这就像在 diff 编辑器里执行“Revert Hunk”,但完全脚本化,适合在自动化管线中快速清理不想要的改动。

将块压缩进其他修订 —— jjc fold

有时候你希望把当前工作区的某段修改并入另一个已有提交(比如主线分支),而不是新建一个提交。jjc fold可满足这种需求,通过--into指定目标修订:

jjc fold a1b --into main           # 将 @ 中的块并入 mainjjc fold a1b -r feat --into main  # 从 feat 修订中取块,并入 mainjjc fold --select feat:a1b,c3d   # 多源显式指派

上面这些操作全部使用统一的代码块选择器语法,支持单个标识符、子原子编号、行范围甚至多个标识符组合。无论拆分、丢弃还是归并,都能通过一条确定性的命令完成,彻底告别逐项勾选的交互流程。

jjc 的出现,让 Jujutsu 的分块操作从手工选择进化到可编程指令。你可以把它嵌入 Makefile、CI 脚本,或者任何需要自动化拆分变更的场景。当代码改动散落在十几个文件中时,只需事先规划好标识符列表,一两条命令就能输出数个语义清晰的提交,而不必在交互界面里反复确认。对追求高效、可复现研发流程的团队而言,jjc 无疑是把分块能力从编辑器里解放出来的利器。