jj 项目 Demos 指南:用可复现脚本生成终端截图,展示 Jujutsu 核心特性
2026/9/10 11:26:23 网站建设 项目流程

jj 项目 Demos 指南:用可复现脚本生成终端截图,展示 Jujutsu 核心特性

【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jj

demos目录是 Jujutsu(jj)项目随仓库自带的可复现演示与截图生成工具集。它以demo_*.sh脚本形式逐个演练jj的 Git 兼容、工作副本自动提交、操作日志与撤销、冲突解决等核心功能,并通过run_scripts.sh标准化环境中运行这些脚本、自动生成 SVG/PNG 图片,供文档与主页展示。读完本篇,你将掌握如何在自己的机器上重放这些演示、如何复现官方仓库中的终端截图,以及每个演示脚本背后的jj命令调用链与设计意图。

一、demos 目录里有什么

先看一下目录构成(demos/README.md 即本指南的说明文档):

  • demo_*.sh演示脚本:每个脚本针对jj的一个特性,运行后会在终端输出带 ANSI 颜色的命令回放:
    • demo_git_compat.sh:演示jj与 Git 的兼容性(克隆、书签跟踪、日志、diff、git format-patch兼容输出);
    • demo_working_copy.sh:演示"工作副本即提交"(working copy as a commit)模型;
    • demo_operation_log.sh:演示操作日志(operation log)与jj op revert/jj op restore/--at-op
    • demo_resolve_conflicts.sh:演示冲突记录在提交中并在工作副本解决;
    • demo_juggle_conflicts.sh:演示重新排序提交、制造冲突并验证"顶提交无冲突"的冲突传播特性。
  • run_scripts.sh:批量运行演示脚本并生成 SVG/PNG 的编排器。
  • helpers.sh:被各演示脚本source的公共工具函数(new_tmp_dirrun_commandcommentblank等)。
  • setup_standard_config.sh:为演示生成隔离的JJ_CONFIGGIT_CONFIG_GLOBAL,保证输出可复现。
  • 产物*.svg*.png(如git_compat.pngworking_copy.pngoperation_log.pngresolve_conflicts.pngjuggle_conflicts.png),其中 PNG 直接用于 README.md 特性章节配图。

二、快速上手:一条命令跑完所有演示

run_scripts.sh可以接收任意数量的demo_*.sh作为参数。文档给出的推荐用法是把输出管道交给less边看边检查:

cd demos ./run_scripts.sh demo_*.sh |less

对每个传入的脚本,run_scripts.sh会依次完成三件事(对应 run_scripts.sh):

  1. term-transcript capture捕获脚本在终端中的彩色输出,生成<script_base>.svg(如demo_git_compat.shgit_compat.svg);
  2. 把捕获的原始输出通过tee同时回显到当前终端,方便你直接观察演示过程;
  3. 若检测到 ImageMagick 的magick命令可用,则进一步把 SVG 转换为 PNG。

2.1 前置依赖

  • term-transcript-cli:必备。它是把 ANSI 终端输出渲染成 SVG 的工具。缺少时会报错并给出安装提示(如cargo binstall term-transcript-cli)。run_scripts.sh通过which term-transcript检查,缺失时直接失败退出。
  • ImageMagick 的magick:可选,仅用于生成 PNG。缺失时脚本会打印提示"只有 SVG 会被生成",但不会中断 SVG 流程。
  • Inkscape:在 Debian 类系统上推荐sudo apt install inkscape,因为 ImageMagick 生成 PNG 时可能依赖 Inkscape 或其依赖库(源码注释里也说明可以用 Inkscape 手工完成 SVG→PNG 转换)。
  • Fira Code 字体(推荐):sudo apt install fonts-firacode。默认在 Debian 上生成截图时使用 Fira Code;未安装时回退到 Liberation Mono(效果也可以),再不行则按 CSS 字体栈回退到系统monospace

2.2 一条命令、两种产物

每个演示脚本最终产出同名的.svg.png两个文件,二者的定位在文档中有明确说明:

  • PNG:仓库中自带的 PNG 可能略微过时,因为体积较大不便于频繁更新提交;
  • SVG:差异(diff)是人类可读的、便于维护;但不同机器因安装字体不同渲染可能略有差异。

三、脚本如何保证"可复现":标准化环境

3.1setup_standard_config.sh:注入隔离配置

演示的输出必须在不同机器上尽量一致,为此 setup_standard_config.sh 为每次运行注入两份临时配置文件(通过环境变量指向mktemp生成的临时文件,不污染用户的真实配置):

# JJ_CONFIG(jujutsu 用户配置) [user] name = "JJ Fan" email = "jjfan@example.com" [operation] hostname = "jujube" username = "jjfan" [ui] color="always" paginate="never" log-word-wrap=true # 需要配合 COLUMNS 使用

要点说明:

  • [user]固定作者身份,保证提交元数据一致;
  • [operation]固定操作记录的 hostname 与 username,保证操作日志渲染一致;
  • [ui] color="always"强制输出 ANSI 颜色(终端截图必需);paginate="never"关闭分页,避免交互卡住脚本;
  • log-word-wrap=true配合RUN_COMMAND_COLUMNS=80实现日志换行。

同时生成GIT_CONFIG_GLOBAL并设置[color] ui=always,确保底层 Git 命令(如git log --graph)也输出颜色,与jj侧保持一致。

3.2helpers.sh:演示脚本的"脚手架"

helpers.sh 提供四个关键函数:

  • new_tmp_dir:用mktemp -d创建一次性临时目录并cd进入,脚本退出时自动清理(trap ... EXIT),保证演示不污染用户环境;
  • run_command:先回显$ 命令,再以COLUMNS=${RUN_COMMAND_COLUMNS:-80}执行命令。80 列是既定的换行宽度——term-transcript在 80 列处换行,而 80 也恰好是移动设备上可读的最大宽度;
  • run_command_output_redacted:执行命令但把真实输出替换成灰色提示... (output redacted) ...,用于隐藏会破坏演示对仗的输出(如工作副本描述的变更);
  • run_command_allow_broken_pipe:把jj在管道破裂时的退出码 3 视为成功(对应jj | head场景);
  • comment/blank:输出绿色注释行与空行,构成截图中的解说文案。

从源码结构看,run_scripts.sh之所以用RUN_COMMAND_COLUMNS而非COLUMNS,是因为bash会重置$COLUMNS,改用自定义变量后由helpers.sh中的run_command()解释,从而稳定控制换行。

四、各演示脚本详解:命令调用链与设计意图

4.1demo_git_compat.sh:Git 兼容性

脚本核心流程(demo_git_compat.sh):

jj git clone https://github.com/octocat/Hello-World cd Hello-World jj bookmark list --all jj bookmark track octocat-patch-1 --remote=origin jj log jj log -r 'all()' jj diff -r b1 jj diff -r b3 jj show --git --template git_format_patch_email_headers git log --graph --all --decorate --oneline

它演示的要点:

  • jj git clone直接克隆 GitHub 仓库,克隆后默认只为远程master创建本地书签master并跟踪远程分支,其余远程分支仅以远程跟踪书签形式存在;
  • jj bookmark track octocat-patch-1 --remote=origin把某个远程分支纳入本地跟踪;
  • 默认jj log会排除未跟踪的远程分支,聚焦"我们自己的"提交;jj log -r 'all()'则显示全部提交(all()是 revset 表达式);
  • jj diff -r b1查看指定提交的差异;
  • jj show --git --template git_format_patch_email_headers生成与git format-patch兼容的补丁输出;
  • 最后用原生git log --graph --all --decorate --oneline证明"仓库底层就是真实的 Git 仓库"(Jujutsu 以 Git 仓库作为存储后端,见 README.md 的 "Compatible with Git" 一节)。

4.2demo_working_copy.sh:工作副本即提交

该脚本用jj git clone进入 Hello-World 仓库,然后依次演示(demo_working_copy.sh):

  1. 初始时工作副本位于master之上、标记为(empty)
  2. 修改README、新增new-file后,jj status显示工作副本不再为空,且其提交 ID(以蓝色字符开头)发生变化——因为工作副本本身就是一个提交,每次快照都会生成新的提交 ID;
  3. jj bookmark create goodbye为当前工作副本提交打上书签;
  4. jj new master从 master 开出新的空提交,原goodbye提交保留——无需git stash,切换即"干净";
  5. jj describe -m可设置任意提交的描述(不只是工作副本),体现"提交是唯一可见对象、工作副本并无特权"的设计(对应 README 中 "The working copy is automatically committed" 一节)。

4.3demo_operation_log.sh:操作日志与撤销/恢复

脚本先克隆并做一点清理,随后执行(demo_operation_log.sh):

jj op log # 查看操作日志 echo stuff > new-file jj describe -m stuff jj rebase --onto test jj new master jj describe -m "other stuff" jj op log --limit 4 rebase_op=$(jj --color=never op log --no-graph -T 'id.short(5)' --limit 1 --at-op @--) jj op revert $rebase_op # 只撤销那次 rebase jj --at-op $rebase_op log # 查看 rebase 之后、后续操作之前的仓库状态 jj op restore $rebase_op # 恢复整个仓库到 rebase 之后的状态

演示意图:

  • jj op log展示 Jujutsu 记录每一次操作(快照、describe、rebase、new 等);
  • jj op revert <op>精确撤销某一次操作——示例中只回退了 rebase,而后续的 "other stuff" 提交不受影响;
  • jj --at-op <op> log以只读方式查看"某个历史时点"的仓库视图;
  • jj op restore <op>则把整个仓库状态回滚到该操作之后;
  • 对应 README 中 "Entire repo is under version control" 一节——整个仓库都在版本控制之下,可以逐条撤销或定向恢复。

4.4demo_resolve_conflicts.sh:冲突的提交内记录与解决

流程(demo_resolve_conflicts.sh):

  1. 克隆后清理测试书签,在工作副本修改READMEHello Earth!)并 describe;
  2. jj rebase --onto b1——rebase 成功返回,但提示产生冲突;
  3. jj log/jj status显示冲突被记录在提交中;工作副本的README呈现冲突标记内容;
  4. 直接echo "Hello earth!" > README解决冲突,jj status不再报告冲突。

要点:冲突不会导致操作失败,而是作为提交的一部分被记录(first-class conflict,参见 README.md 的 "Conflicts can be recorded in commits" 一节与 docs/conflicts.md)。无论哪个命令引发冲突,都收敛到"在提交里记录冲突、稍后统一解决"这一条工作流,无需git rebase --continue之类的中断续接机制。

4.5demo_juggle_conflicts.sh:冲突的"腾挪"

这是最能体现 Jujutsu 冲突传播能力的演示(demo_juggle_conflicts.sh):

  1. 先用jj debug init-simple在临时目录初始化一个"简单后端"仓库,创建三个连续提交first/second/third,都修改同一行文件;
  2. jj rebase -s third --onto firstjj rebase -s second --onto third交换二、三提交的顺序——结果"third" 提交出现预期冲突,而最顶上的提交没有冲突,因为它聚合了三个提交的全部变更;
  3. jj new secondcat file验证内容确为third的最终状态;
  4. 换个玩法:让secondthird成为兄弟提交并用jj new second third -m merged合并——合并提交同样因聚合了全部变更而无冲突。

这个演示背后是 Jujutsu 将冲突作为一等对象建模的机制:rebase 时冲突信息被携带并传播到后代提交;当某个提交聚合了冲突各方的全部变更时,冲突自动消失。这也是 "Automatic rebase and conflict resolution"(README.md)中"透明版的git rebase --update-refs+git rerere"能力的直观体现,底层实现可参考 lib/src/conflicts.rs、lib/src/merged_tree.rs 与 cli/src/commands/rebase.rs。

五、run_scripts.sh生成图片的技术细节

5.1 SVG 生成:term-transcript capture

run_scripts.sh 中关键调用:

term-transcript capture \ --no-inputs --pure-svg --palette powershell \ --font "Fira Code, Liberation Mono, SFMono-Regular, Consolas, Menlo" \ --out "$script_base".svg "$script_base" < "$outfile"
  • 之所以用term-transcript capture而非term-transcript exec,是为了能通过tee把脚本输出同时展示出来;
  • --palette powershell指定配色;
  • --font指定字体优先级列表——term-transcript的默认字体栈是SFMono-Regular, Consolas, Liberation Mono, Menlo,脚本把"经验证包含全部相关 Unicode 符号"的 Fira Code 等字体排在前面(脚本里有关于字体渲染的注释说明)。

5.2 PNG 生成:magick

SVG 默认按 1 SVG 单位 = 1 像素输出,宽度 720 单位。转 PNG 时:

magick -background black "$script_base".svg \ -type Palette -colors 63 -resize 100% \ "$script_base".png
  • -background black很关键:SVG 用透明实现圆角,若不指定背景,透明区域默认会变成白色;
  • -type Palette -colors 63做调色板量化压缩;
  • -resize 100%目前是空操作,改为-resize 700x10000可把宽度压到 700px 并保持宽高比;
  • 脚本注释特别提醒:PNG 透明与这里的操作顺序是"反直觉"的,编辑时需小心(并引用了 ImageMagick 的讨论线索)。

最终,README.md中各个特性小节直接引用了这些产物图片(demos/git_compat.png 用于 "Compatible with Git",demos/working_copy.png 用于 "The working copy is automatically committed",demos/operation_log.png 用于 "Entire repo is under version control",demos/resolve_conflicts.png 与 demos/juggle_conflicts.png 用于 "Conflicts can be recorded in commits")。

六、字体与输出差异的注意事项

文档明确提醒:PNG 的最终渲染取决于本机安装的字体。官方截图通常在 Debian Linux 上生成,使用 Fira Code 字体;convert -list Fonts可以列出 ImageMagick 能识别到的所有字体。如果某台机器没有 Fira Code,会退而使用 Liberation Mono(也够用),SVG 在网页上查看时则依赖 CSS 字体栈逐级回退。因此,如果你在本地重新生成截图,看到的字体渲染可能与仓库内置 PNG 略有不同——这是预期行为,不必视为异常。

七、小结:这套 Demos 的价值

demos/是一套"自带文档的演示基础设施",其价值在于:

  1. 可重放:任何人在装好term-transcript(+ 可选magick)后,都能一键复现与官方完全一致的演示输出;
  2. 可校验:脚本中的每条命令都真实执行,若某条jj命令行为变化导致输出异常,脚本会以退出码或异常输出暴露问题(配合set -euo pipefail);
  3. 即文档helpers.shcomment()把解说词直接嵌入脚本,截图本身就是图文并茂的教程;而 README.md 又把这些截图作为特性说明的配图,形成"脚本 → 截图 → 文档"的闭环。

如果你想深入了解这些演示涉及的jj命令的完整参数,可查阅 cli/docs/cli-reference.md(jj help的文本版)与 cli/docs/tutorial.md(入门教程);想研究底层冲突机制,可从 lib/src/conflicts.rs 与 docs/conflicts.md 入手。

【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jj

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询