Jujutsu 对抗 git:git 从没有过的撤销键
撤销做坏的 rebase、把冲突 commit 进历史、一个 clone 跑两套工具 —— 读的是项目档案而不是营销,诚实线:读了,没跑。
jj 把每一次操作记进 op log; jj undo能把做坏的重放或回带着你原路退回 — git 的 reflog 只救 commit。
默认存储与 git 兼容: 一个 clone,两套工具 —— remotes、托管平台、CI 照常运转。
档案记录说:在边角项目上先并列部署试水;不是一口吞的迁徙 —— 它还是 0.x,破坏性变更每月随版本到站。
两条时间带
按下操作。commit 带(git)和操作带(jj)并排记录 —— 然后试着把最后一条撤回去。
带子还是空的 —— 按一个操作。
GIT · reflog —— commit,约 90 天
reflog 对弄出这一摊烂账的命令顺序没有立场 —— 逆向命令你自己挑:reset?revert?cherry-pick?
JJ · op log —— 每一笔操作
「因为一切都被记录,你刚犯的那个错都能轻松撤回」 —— README 自己的那句话。 jj op log · jj undo。
git 的撤销剧本假设你会挑对命令;jj 的剧本假设你挑不对。
从档案记录看 jj 是什么
jj 是一个与 git 兼容的 VCS: GitHub 31,796 颗星、376 位贡献者、2020 年 12 月首发,从那以后每个月都发一版
从 v0.35(2025 年 11 月)到 v0.45.1(2026 年 9 月),十二个版本,走时准得像钟表。
「与 git 兼容」是人们错过的那部分:jj 默认用 git repo 当存储 —— commit 和文件都以 git 的格式存着。clone、remotes、托管平台和 CI 照常运转。
搜「jujutsu vs git」架错了框:jj 是一套新界面,拧在你已经信任的存储上。
(Meta 反着押 Sapling —— 自家存储 —— 为此多付了 git 生态之外的成本。)
可以 commit 进历史的冲突
能 —— 冲突在这里是一等对象,这一点比 undo 的故事更重要。git 把 merge 冲突当作工作树的临时状态:现在就解,不然点 abort。
jj 把冲突存进历史:一个处于冲突状态的 commit 可以存在、被 commit、甚至被 push。
事后再解;jj 把修法传给每一个后代 —— 和给你的叠层做 rebase 用的是同一套机制。
「叠着的 PR 做多分支 rebase 不费劲。冲突是历史里实实在在的东西,可以回头再解。一切自动 commit,所以糟糕的 reset/stash pop 再也丢不了我的活。」 —— hellcow,Hacker News 上聊 jj 用法的(236 分)
最后这句才是重点:jj 的工作副本本身就是个 commit,每次改动都自动修订。
没有 stash,因为没有东西需要 stash —— 切分支时,你的活儿以 commit 的形式跟着走。
另一位在纯 git 职场的转用者:「零问题。」
档案说要提防 jj 的地方
- 诚实说:0.x。 一年十二个版本,也意味着每月十二次撞上破坏性变更的机会。项目发版快,自己也这么说。
- bookmarks 不放在 git 里。 commit 和文件用 git 存储;分支元数据用 jj 自家格式。并列克隆在两边搭桥 —— 多出一件要理解的活零件。
- 1,262 个未关 issues。 项目健康,欠账是真欠账。
- 怀疑者仍然有说对的地方。 那个 HN 帖子里赞数最高的保留意见: 「关于 jj 我已经读过好几遍了,但它究竟解决什么问题,我还是没搞明白。」 如果你的 git 流程就是一条分支、偶尔一个 merge,操作日志改变不了你这一周。收益要在叠着干活、历史带了冲突、undo 用得凶的日子里才到账。
该不该换?
判词,和诚实线: 我读的是档案记录,没跑过。
这里的每个数字和引文都来自仓库、它的 README 和 Hacker News 帖 —— 不出自我自己的终端。
档案支持的做法:在边角项目上并列部署地试 jj —— 一个 clone,两套工具,零迁移。git 的知识直接带过去;团队按人头逐个收编,因为 jj 推的还是普通 git commit。
档案不支持的做法:让一个成型的团队一口吞迁移,或在钉住观察期之前,把关键的发版自动化交给一个 0.x 工具托底。
undo 的裂缝是真的,设计是自洽的,互操作性把借口拿掉了 —— 剩下的只有习惯。
只用一个周末的肌肉记忆,换一本连工具本身都盖住的 undo 账本,你换吗?
再说句实话 —— 你上一次因为 reset 丢活儿是什么时候?reflog 全捞回来了吗?
两条时间带到此为止 · 没有任何 fetch · 全程本地