Skip to content

Instantly share code, notes, and snippets.

@lxl66566
Created March 25, 2026 09:47
Show Gist options
  • Select an option

  • Save lxl66566/1ded55f6193c24af296f06c056de5799 to your computer and use it in GitHub Desktop.

Select an option

Save lxl66566/1ded55f6193c24af296f06c056de5799 to your computer and use it in GitHub Desktop.
lxl66566's jujutsu config (20260325)
# :schema https://docs.jj-vcs.dev/latest/config-schema.json
# some contents are from https://gist.github.com/thoughtpolice/8f2fd36ae17cd11b8e7bd93a70e31ad6
[user]
name = "lxl66566"
email = "lxl66566@gmail.com"
[ui]
# 当只输入 `jj` 时,默认执行的命令设为 `jj log` (查看日志)
default-command = "log"
# 默认的 diff 差异对比工具设置为 `difftastic` (对应的命令是 difft)
diff-formatter = "difft"
# 设置解决代码冲突时默认使用的编辑器为 vscode
merge-editor = "vscode"
# 在 log 界面中,对隐藏/被省略的节点生成一个合成标记进行提示
log-synthetic-elided-nodes = true
# 提交树图表的边框绘制样式,设置为 "square"(方形折线风格)
graph.style = "square"
# 提交代码时自动在提交信息末尾添加 Signed-off-by (开发者认证) 的签名
should-sign-off = true
[merge-tools.difft]
# 为 difftastic 配置具体的合并/差异工具参数
program = "difft"
# 设置传递给 difft 的参数:永远显示颜色,并传入左侧和右侧的文件
diff-args = ["--color=always", "$left", "$right"]
[git]
# 配置 push 推送时,自动生成的书签名的前缀
push-bookmark-prefix = "lxl66566/push-"
# 指定绝对不应该被推送到 Git 远端的私有提交过滤规则
# (这里调用了下方 [revset-aliases] 中定义的 blacklist() 函数别名)
private-commits = 'blacklist()'
# colocate = true # 是否开启 colocate 模式 (将 jj 的存储库和 git 存储库放在同一目录下混合使用)
# 自动在提交说明(commit message)的头部写入 Change-Id (这是 Gerrit 代码审查平台需要的格式)
write-change-id-header = false
[snapshot]
# 自动更新过期的工作副本 (working copy)
auto-update-stale = true
# 当 jj 命令在 "xxx" 目录及子目录中运行时触发的配置
[[--scope]]
--when.repositories = ["C:/programs/work"]
[--scope.user]
name = "..."
email = "..."
[remotes.origin]
auto-track-bookmarks = "*"
[fsmonitor]
# 使用 watchman 作为 fsmonitor,提升性能(需要安装 watchman)
backend = "watchman"
watchman = { register-snapshot-trigger = true }
[aliases]
f = ["git", "fetch", "--all-remotes"]
p = ["git", "push", "--tracked"]
l = ["log", "-r", "(trunk()..@):: | (@..trunk())::"]
s = ["squash"]
c = ["commit", "-m"]
n = ["new"]
e = ["edit"]
init = ["git", "init", "--colocate"]
mark = ["bookmark", "set", "-r", "@"]
# "New Trunk":快速基于主干新建一个提交
nt = ["new", "trunk()"]
# 更短(因而更好用)的命令名称,相当于 git blame
credit = ["file", "annotate"]
# 相当于 git show,查看指定文件内容
cat = ["file", "show"]
# 简化提交节点的父级关系
streamline = ["simplify-parents"]
# 找到离当前工作节点最近、且带有书签的祖先节点,并将其移动到当前工作副本的父节点上。
tug = ["bookmark", "move", "--from", "heads(::@- & bookmarks())", "--to", "@-"]
# 获取所有活跃的工作栈
open = ["log", "-r", "open()"]
# 重新挂载到主干(Retrunk)。通常配合 `jj retrunk -s ...` 使用。
# 配合上面的 open 别名:jj retrunk -s 'all:roots(open())'
retrunk = ["rebase", "-d", "trunk()"]
# 将当前工作栈“重新加热”(reheat) —— 即将当前工作栈衍合 (rebase) 到主干。
reheat = ["rebase", "-d", "trunk()", "-s", "all:roots(trunk()..stack(@))"]
# 三明治模式 ('jj sandwich xyz'):将节点 xyz 连同其他提交平行放入 megamerge 中。
# 解析方式请参考上面对 'megamerge()' 的原理解释。
sandwich = ["rebase", "-B", "megamerge()", "-A", "trunk()", "-r"]
# 从任何指定修改节点中吸取内容,然后合并进当前的 @ 工作副本里。这是 'eject' 的逆向操作。
# 示例: jj consume xyz path/to/file
consume = ["squash", "--into", "@", "--from"]
# 将当前 @ 里的特定内容弹出 (eject) 到任意修改节点里。这是 'consume' 的逆向操作。
# 示例: jj eject xyz --interactive
eject = ["squash", "--from", "@", "--into"]
# 实验功能:超级通用命令,融合了 'diff' 和 'show' 的功能,用于详细检查节点详情。
examine = ["log", "-T", "builtin_log_detailed", "-p", "-r"]
## Revsets 是 jj 中用来过滤、查询提交节点 (commits) 的表达式语言
[revsets]
# 定义 jj log 默认显示的查询条件。
# 默认显示:所有属于我的工作栈 (mine() | @) 或者 主干分支 trunk() 或者 当前节点 @
log = 'stack(mine() | @) | trunk() | @'
# 在日志图表的渲染中调整节点优先级,使得 megamerge(大合并) 始终显示在提交图的“最左侧”
log-graph-prioritize = 'coalesce(megamerge(), trunk())'
[revset-aliases]
# 给当前节点符号 "@" 设置别名为 "at"。
# 在 Windows 终端里直接输入 @ 可能会有解析问题,用 at 会很方便。\
'at' = '@'
# 待修复 (上游问题): 这些别名是否应该被内置到上游 jj 仓库中?
# 匹配指定作者(author)或提交者(committer)的提交
'user(x)' = 'author(x) | committer(x)'
# 匹配所有属于“我”的提交 (包含了前面配置的两个邮箱)
'mine()' = 'user("aseipp@pobox.com") | user("austin@ersc.io")'
# 默认情况下,包含目标仓库的主干(trunk)、远程书签(remote bookmarks)以及所有标签(tags)。
# 大多数情况下我们不想更改这些内容,但在某些特定的仓库结构下会有用。
'immutable_heads()' = 'present(trunk()) | untracked_remote_bookmarks() | tags()'
# 忽略并隐藏针对 gh-pages (GitHub Pages) 分支的提交。
# 在很多仓库中(比如 jj 自己的源码库),这些分支会不断产生大量自动生成的提交,
# 将它们隐藏掉能让日志界面更清爽。
'gh_pages()' = 'ancestors(remote_bookmarks(exact:"gh-pages"))'
# 匹配私有 (private) 以及正在进行中 (wip) 的提交。这些提交绝对不能被推送到任何远端。
# 它们通常是正在开发中的合并栈 (merge stacks) 的一部分。
'wip()' = 'description(glob:"wip:*")'
'private()' = 'description(glob:"private:*")'
'blacklist()' = 'wip() | private()' # 黑名单,包含了 wip 和 private
# stack(x, n) 代表从节点 'x' 出发可以触达的“可变(mutable)”提交集合,拥有 'n' 个父节点。
# 'n' 经常被用来定制特定操作的展示和返回集合。
# 'x' 用来指定要遍历的“根(roots)”集合,例如 @ 就代表当前的工作栈。
'stack()' = 'stack(@)'
'stack(x)' = 'stack(x, 2)'
'stack(x, n)' = 'ancestors(reachable(x, mutable()), n)'
# 当前的“开放 (open)”工作集。定义为:
# 从我的当前工作区出发能触达的所有提交栈,或者包含我自己写的任何其他提交。
# 这里的 n = 1 意味着排除了 `trunk()` 主干包含的内容,所以按定义该集合返回的全是可变的提交。
'open()' = 'stack(mine() | @, 1)'
# 抄来的,我一般不用。
# 查找 megamerge (大合并)。它在配合其他别名(主要是下方的 'sandwich' 别名)时非常有用。
# 通常情况下如果只有一个 megamerge,sandwich 会完美发挥类似“魔法”的作用。
# 但是遇到复杂情况时;考虑下面这个模拟上游分叉 (fork) 仓库的情况:
#
# ----> P1 ... Pn -----------\
# / \
# /---> X --\ (main) \
# B M1 --> T1 ... Tn --> M2 --> @
# \---> Y --/
#
# 这里 X 和 Y 是在基准点 B 之上的典型功能提交,它们在 megamerge M1 中被合并。
# 但是,我们可能想把 T1...Tn 这些变更挂载在 M1 之上,因为(在我的使用场景中)
# 这些变更是高度定制的,永远不会合并到上游仓库,但应该被发布在 fork 库里;
# Tn 就是 main 书签指向的位置。
# 最后,我们还有 P1...Pn 这样的私密更改,它们绝不应该被推到上游。
#
# 在这种复杂场景下,sandwich 操作会失败。因为 'reachable(stack(), merges())'
# 会找到 {M1, M2} 两个合并节点,缺少 all: 前缀修饰符的情况下这无法传入 'rebase -B'。
# 为了处理这个问题,我们允许用户显式设置一个名为 "megamerge" 的书签/标签。
# 只要执行 'jj bookmark set megamerge -r M1',sandwich 就能完美地按预期工作了。
'megamerge()' = 'coalesce(present(megamerge), reachable(stack(), merges()))'
[colors]
# 基础界面元素的终端颜色配置
"normal change_id" = { bold = true, fg = "magenta" } # 正常节点的 change_id 是加粗品红色
"immutable change_id" = { bold = false, fg = "bright cyan" } # 不可变节点的 change_id 亮青色
# log 命令中图表节点的模板颜色
"node" = { bold = true } # 默认节点加粗
"node elided" = { fg = "bright black" } # 被省略折叠的节点:亮黑色(灰色)
"node working_copy" = { fg = "green" } # 当前工作副本节点:绿色
"node conflict" = { fg = "red" } # 产生冲突的节点:红色
"node immutable" = { fg = "bright cyan" } # 不可修改的只读节点:亮青色
"node wip" = { fg = "yellow" } # 包含 wip 标记的节点:黄色
"node normal" = { bold = false } # 普通节点取消加粗
# 其他各种模板中文字的颜色
"text link" = { bold = true, fg = "magenta" } # 文本超链接:加粗品红
"text warning" = { bold = true, fg = "red" } # 文本警告:加粗红色
[template-aliases]
# 生成能在终端中点击的超链接(Hyperlink)代码 (终端需支持 OSC 8 转义序列)。
'hyperlink(url, text)' = '''
concat(
raw_escape_sequence("\e]8;;" ++ url ++ "\e\\"),
label("text link", text),
raw_escape_sequence("\e]8;;\e\\"),
)
'''
# 基本样式格式化设定。
# 短签名格式化:检查作者是否有 email,没有的话红字警告 "NO EMAIL"。
'format_short_signature(signature)' = '"<" ++ if(signature.email(), signature.email(), label("text warning", "NO EMAIL")) ++ ">"'
# 时间戳格式化:如 "[2 hours ago]"
'format_timestamp(ts)' = '"[" ++ ts.ago() ++ "]"'
# 渲染书签列表:如果是远端书签直接显示,如果是本地书签,生成通往 GitHub PR 基准分支的超链接
'render_bookmarks(commit)' = '''
commit.bookmarks().map(|b|
if(b.remote(),
b,
hyperlink(gh_pr_base() ++ "/tree/" ++ b.name(), b),
)
)
'''
[templates]
# 默认推送分支名
git_push_bookmark = '"lxl66566/push-" ++ change_id.short()'
# 改进 log 图表中节点的默认视觉展示。为不同状态的节点上色并替换图标。
# 操作日志中的节点图标 (当前操作显示为 @,其他显示为 ◉)
op_log_node = 'if(current_operation, "@", "◉")'
# 提交图谱中的节点图标定义
log_node = '''
label("node",
coalesce(
if(!self, label("elided", "⇋")),
if(current_working_copy, label("working_copy", "◉")),
if(conflict, label("conflict", "x")),
if(immutable, label("immutable", "◆")),
if(description.starts_with("wip: "), label("wip", "!")),
label("normal", "○")
)
)
'''
# 自定义处于草稿阶段的 commit 描述模板。
# 这里实现了自动追加信息:
# - 如果开启 gerrit.enabled 则生成 Gerrit 的 Change-Id 行。
# - 如果开启 ui.should-sign-off 则添加 Signed-off-by (开发者认证) 信息。
draft_commit_description = '''
concat(
description,
"\n",
if(
config("ui.should-sign-off").as_boolean() && !description.contains("Signed-off-by: " ++ author.name()),
"\nSigned-off-by: " ++ author.name() ++ " <" ++ author.email() ++ ">",
),
"\n",
surround(
"\nJJ: 此提交包含以下变更:\n", "",
indent("JJ: ", diff.summary()),
),
)
'''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment