Jujutsu 设计文档蓝图(Design Doc Blueprint):为 jj 新特性撰写技术提案的完整指南
Jujutsu 设计文档蓝图Design Doc Blueprint为 jj 新特性撰写技术提案的完整指南【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jjJujutsujj在推进大型技术决策时依赖一套正式的设计文档Design Doc流程任何涉及新组件或重大改动的特性都必须先通过评审才能合入代码。本文以仓库中的 docs/design_doc_blueprint.md 模板为骨架结合 docs/design_docs.md 的流程说明与 docs/design/ 目录下 9 篇真实设计文档如jj run、jj converge、Sparse Patterns v2、Copy Tracking 等系统讲解如何为 Jujutsu 撰写一份结构完整、论据扎实、可评审通过的设计提案。读完本文你将掌握 jj 设计文档的全部章节含义、每个章节应填入什么内容、以及如何引用仓库源码与既有设计作为证据支撑。Jujutsu 设计文档机制概述设计文档是 Jujutsu 社区驱动技术决策的核心工具。根据 docs/design_docs.md该机制与 Rust RFC 流程有相似之处但主要面向技术问题本身并兼顾所有利益相关方的技术与社区关切在大型项目或新组件上设计文档用于驱动技术决策是讨论提案的地方流程非常严格设计文档必须先获得批准相关功能的 PR 才会被接受如果你想为 Jujutsu 构建原生后端native backend或服务端组件就必须走完这个流程。标准流程四步走在docs/design/目录下新建一个 Markdown 文档以你要改进的功能或项目命名例如docs/design/run.md、docs/design/jj-converge-command.md、docs/design/sparse-v2.md描述当前世界的状态以及你想要改进的内容等待维护者Maintainers与利益相关方Stakeholders出现并参与评审以常规代码评审的方式反复迭代直到所有人都接受这个变更。设计文档的最终产出是仓库根目录下的 docs/design_doc_blueprint.md即本文接下来要逐节拆解的蓝图模板。蓝图模板逐节拆解以下每个小节都对应蓝图中的一个章节并附上真实设计文档中的对应实例帮助你理解该写什么、怎么写。标题与作者信息Title / Author每篇设计文档需要一个有辨识度的标题并在标题下方注明作者及可联系邮箱。蓝图要求# Title A cool name for your Project Author: [Your-Name](mailto:your-namereachable.com)实际文档中的做法可以参看 docs/design/run.md 的开头# Introducing JJ run Authors: [Philip Metzger](mailto:philipmetzgerbluewin.ch), [Martin von Zweigberk](mailto:martinvonzgoogle.com), ...多个作者时依次列出即可。jj-converge-command.md还额外在标题下方提供了Summary摘要段用 2~3 句话交代这份文档提出什么命令、解决什么问题方便评审者快速判断主题相关性。部分文档还会标注状态如 docs/design/managed-config.md 的Status: Pending implementation或初版日期如run.md标注Initial Version, 10.12.2022。Summary摘要蓝图要求用 3~10 句话概括你的项目 / 重新设计 / 组件以及它解决的问题。摘要应当做到一句话点明提案是什么例如jj run是在多个 revision 上运行用户提供的命令或脚本以无缝集成构建系统、linter 和 formatter说明它解决的核心痛点给出后续详情的锚点链接。run.md的摘要是一个很好的范本它先声明本文档设计 jj 的新run命令紧接着列出典型用途build systems、linters、formatters并链接到文内的 Use-Cases 小节。摘要不是执行摘要的缩写而是让评审者 30 秒内判断这份提案是否与我相关的门面。State of the Feature as of$VERSION当前状态可选如果该功能已有现状用这一节说明截至某个版本现状是什么、短板在哪里。如果没有可对照的现状则整节省略。例如 docs/design/sparse-v2.md 的 Current State (as of jj 0.13.0) 明确写道稀疏模式Sparse Patterns本质上是无顺序的字符串前缀列表path/one path/to/dir/two文件集合由匹配任意前缀决定状态存放在未纳入 Op Store 版本管理的工作副本状态文件中。由于所有路径都是裸字符串、没有转义或更高层格式现行设计很难新增排除规则或路径重映射等特性——这正是 Sparse Patterns v2 要解决的问题。另一个范例是 docs/design/tracking-branches.md 的 Current data model (as of jj 0.8.0)它用数据模型图列出branches、tags、git_refs、git_head的现有结构并点出现有模型的两个缺陷jj branch forget与 colocated 工作区的jj op revert会导致远端分支与 git refs 失步git伪跟踪分支需要特判。写作要点写明版本号如as of jj 0.13.0用可验证的结构化描述数据结构、命令行为代替模糊吐槽为后面的 Goals 提供要改什么的依据。Prior work既有工作可选如果该特性在其他地方已经存在用这一节记录它的做法与做出的取舍如果没有先例则改用文末的 Related Work 节。run.md的 Preface 是典型示例它列举了五种先例并逐一给出简短结论git testgit-branchless 的一部分与jj run提案最接近hg runGoogle 内部 Mercurial 扩展与jj run类似但依赖 CitC 虚拟文件系统做惰性应用而当前 jj 的开源后端Git、Simple都没有支持它的虚拟文件系统因此暂时只能在普通本地磁盘工作副本中运行命令——这是一个非常关键的取舍陈述hg fixGoogle 开源 Mercurial 扩展更专注于在缺乏完整工作目录上下文时重写文件内容git rebase -x在 rebase 过程中机会式地运行命令git bisect run运行命令定位引入 bug 的提交。写作要点先例的价值在于证明你研究过别人怎么做的并显式记录为什么不能直接照搬这往往决定了方案的技术路线如run.md因缺少虚拟文件系统而放弃hg run的优化路径。Goals and non-goals目标与非目标这是设计文档最重要的章节之一。蓝图要求直接列出项目目标以及明确不值得做的特性。run.md提供了一个教科书级的示例Goals目标命令可应用到任意 revision已发布或未发布可并行运行命令同时保持良好的控制台输出命令可在任意提交包括工作副本提交中工作存在某种方式发出硬失败信号为jj test、jj fix、jj format建立足够的基础设施主要目标是足够好因为未来随时可以扩展功能。Non-Goals非目标不应把jj test/jj format/jj fix的用例塞进jj run只建基础不包办命令不应过于聪明过多的 workflow 假设会让用户困惑避免对输出做智能缓存用户输入命令不可预测不做细粒度的面向用户的配置属于无谓的复杂度不提供fix子命令会过度切割设计空间。写作要点Non-goals 的价值不亚于 Goals。它防止评审时出现为什么不顺便支持 X的无休止蔓延也是后续版本迭代的边界声明。注意run.md的非目标里把智能缓存和过于聪明各写了两遍——这恰好说明非目标之间允许语义重叠评审讨论中反复出现的顾虑值得被显式记录。Overview概览与 Detailed Design详细设计Overview 是对项目及其带来的改进的详细综述其中必须包含Detailed Design 小节蓝图明确要求在这里描述所有新接口与交互以及它如何融入现有代码和行为这是所有与系统交互的细节的安放之处。这通常是设计文档篇幅最大的部分不同文档的组织方式差异很大以下是三种有代表性的写法1. 数据模型驱动docs/design/sparse-v2.md先给出完整 Rust 结构体定义再讲 CLI 语法。Sparse Patterns v2 用WorkingCopyPatterns对象取代裸字符串列表并给出SparsePatternsPathTypeDir/Files/Exact与include布尔字段pub enum SparsePatternsPathType { Dir, // Everything under path/... Files, // Files under path/* Exact, // path exactly } pub struct SparsePatternsPath { path_type: SparsePatternsPathType, include: bool, // True if included, false if excluded. path: RepoPathBuf, }同时给出 CLI 的紧凑语法与等价命令(include|exclude):(dir|files|exact):pathjj sparse set --add foo/bar等价于jj sparse set --add include:dir:foo/barjj sparse set --add exclude:dir:foo/bar新增一条Dir类型、include false的规则文件是否被包含由逆序第一条匹配规则决定2. 算法与示例驱动docs/design/jj-converge-command.mdjj converge文档用大量 ASCII 提交图 推导公式讲解分歧合并算法。它提出一个MergedState数据结构每个字段按P (B/0 - P) (B/1 - P)的方式合并struct MergedState { author: MergeSignature, description: MergeString, parents: MergeVecCommitId, tree: MergeMergedTree, }并推导出解决方案父提交的求解公式示例 3parents P⁻ (B/0⁻ - P⁻) (B/1⁻ - P⁻)当结果平凡可解trivially resolves时直接采用否则提示用户选择。它还提出新的try_resolve_deduplicating_same_diffs方法来解决截断演化图场景——这正是 Sparse Patterns 文档之外的另一种 Detailed Design 写法先讲清楚算法与期望行为再讲数据结构。3. 流程与状态机驱动docs/design/tracking-branches.md用 ASCII 流程图描述 import/export 数据流用 Rust 伪代码描述状态决策fn default_state_for_newly_imported_branch(config, remote) { if remote git { State::Tracked } else if matches_auto_track_bookmarks { State::Tracked } else { State::New } }写作要点无论采用哪种组织方式Detailed Design 都必须回答接口长什么样、边界行为是什么、与现有代码如何交互。真实文档通常会包含命令行为示例表如 tracking-branches.md 的 fetch/import、push、export、undo fetch 各种分支场景逐一列出预期行为因为评审者对边界情况的关注远多于对主路径的关注。Alternatives considered备选方案可选记录其他备选方案及它们为何不可行。这一节的存在能大幅减少评审中的重复争论。优秀的备选方案分析需要逐条给出否决理由。docs/design/copy-tracking.md 是范例它分析了三种备选模型并各给出硬伤像 Git 一样即时检测拷贝Git 不记录拷贝信息而是在比较两棵树时推断。它很难扩展到超大仓库——例如把本地提交 rebase 到领先 100 万提交的上游时想找出本地文件中哪些在上游被拷贝过靠比较新旧 base 树代价极高在树中记录逻辑文件标识符BitKeeper 模型难以扩展支持拷贝只支持重命名在 Git 后端也难以合成文件 ID把拷贝信息放进 FileIdMercurial 模型Mercurial 把拷贝信息存在文件内容的元数据段只记录最近一次拷贝文件被修改后 ID 会变需要沿文件历史回溯——与快照模型融合得不如提案优雅。jj-converge-command.md的备选方案更简短但同样有效自动解决分歧应在引入第二个可见提交时就避免需单独调研、两两解决分歧提案的算法本就可处理任意数量分歧提交、只考虑演化分叉点与可见提交示例 6 已证明会导致次优启发式结果。写作要点每个备选方案至少要写它是什么 一个具体的、可论证的失败原因。切忌只列名字不给理由。Issues addressed解决的 Issue可选列出该设计所解决的问题清单。许多设计文档将 issue 编号直接嵌入正文例如run.md提到 [pre-commit 相关的 GitHub discussion] 与 [git-hook 模型的 Discord 讨论]对应#405号 issue、jj op log的整合等待#963号 issuetracking-branches.md的 Objective 直接引用#1136多 Git remote 场景下本地分支交互不佳sparse-v2.md引用#1896更灵活匹配规则与#2288客户端路径重映射。写作要点用 issue 链接把设计文档与社区讨论历史绑定评审者可以回溯问题提出的原始语境。若设计同时解决多个 issue可列成清单。Related Work相关工作可选如果其他 VCS 中存在与你的提案有相似之处的特性放在这里。蓝图给了一个极佳的例子Jujutsu 稀疏工作区与 Perforce 客户端工作区client workspaces。sparse-v2.md的附录扩展了这一思路Perforce client maps 与整个WorkingCopyPatterns概念非常相似设计目标就是达到类似功能Josh Project 则用与稀疏模式相似的方式实现部分 Git 克隆。copy-tracking.md则在正文中详细对比了 Git / Mercurial / BitKeeper 三种模型见前节并把 Mercurial 的hg run、git-branchless 的git test等列为run.md的相关工作。写作要点Related Work 与 Prior work 的区别在于——前者强调功能相似的其他系统实现后者强调同一项目内或直接前身的工作。两者都可能需要也可以相互引用。Future Possibilities未来可能性记录讨论期间可以加入但暂定超出范围的事情。这是防止有价值想法在评审中被丢弃的安全网。run.md的 Future possibilities 包括在内存中重写文件一个巧妙的优化暴露内部状态以实现更精确的资源约束虚拟文件系统的集成选项用于缓存所需工作副本Jujutsu 全局的缓存工作副本概念物化代价高定制化失败消息对机器人有用可类比 Bazel 的select(..., message ...)让jj run异步化派生main进程、立即返回用户、增量更新jj st的输出。git-submodules.md则用 Phase ?: An ideal world 记录了理想世界的成果如重写子模块提交时正确重写后代并更新超级项目的 gitlink、操作日志捕获子模块变更等。写作要点每一项未来可能性都应是一句话可说明的独立想法方便后续有人单独立项时直接引用。从蓝图到落地如何用真实设计文档对照自检在提交设计文档前可以用仓库中已落地的设计文档做对拍检查。以下是三个高价值对照点1. 命令设计类提案对照jj runrun.md的 Command Options 一节给出了完整的命令选项设计可参看jj run最终实现于 cli/src/commands/run.rs--command第一个参数命令名的显式写法-x为 Git 兼容保留可别名到其他命令-j, --jobs并行度-k, --keep-going失败后继续可别名到其他命令--show展示受影响 revision 的 diff--dry-run只记录所有预期的文件与参数不实际执行--rebase/--reparent将受影响 revision 的父提交改为新变更--clean移除既有工作区并清除被忽略文件--readonly忽略多次 run 调用之间的变更--error-strategycontinue|stop|fatal对应 Dealing with failure 一节的三种失败策略。注意该文档明确写出默认情况下jj run作用于当前工作副本并逐一说明了与jj log、jj diff、jj st、jj op log、jj undo等其他命令的整合方式——命令设计文档必须交代与其他命令的交互面。2. 数据模型类提案对照 Sparse Patterns v2sparse-v2.md展示了旧格式兼容 新格式升级的完整迁移路径View 对象中wc_commit_ids: HashMapWorkspaceNameBuf, CommitId演变为带wc_patterns_id的WorkingCopyInfo结构且老 View 在读取时会自动补上当前工作副本模式迁移期至少 6 个月。它还给出了**规则规范化Canonicalization**的严格定义——4 组功能等价的规则集应被统一重写为最小规范形式要求每条规则都影响功能无冗余规则且按字典序排序但/排在所有字符之前便于构建路径前缀树。3. 安全类提案对照 Secure Configdocs/design/secure-config.md 提供了另一种详实度标准它先建立威胁模型从无知识攻击者到极高级重放攻击共 4 个攻击向量逐一说明防御所需条件再给出详细设计。其中zip 文件问题zip 文件问题攻击者打包仓库发送给受害者受害者解压后运行jj fix即执行[fix.tools.foo] command [malicious, command]已成为 jj 配置安全讨论中的标志性概念并直接催生了 docs/design/managed-config.md 的仓库托管配置repo-managed configuration设计——后者用TrustLevel枚举UNSET/IGNORED/TRUSTED/NOTIFY/REVIEW把是否信任仓库提供的配置的选择权交给用户。这些文档之间的引用关系本身就是设计流程的体现一份新设计文档可以引用并扩展旧设计managed-config.md引用secure-config.md的metadata.binpb机制评审者因此能沿着文档链理解设计演进。设计文档中的源码级细节以 Merge 算法为例设计文档的 Detailed Design 经常直接引用核心数据结构的源码语义评审者据此判断提案与现有抽象是否兼容。jj-converge-command.md中的MergeT、SameChange::Accept、resolve_trivial都是对 jj 核心冲突代数conflict algebra的引用其真实实现位于 core/src/merge.rs第 109~122 行定义了SameChange枚举Keep保留同变更冲突不解决与Accept将同变更冲突视为一侧未变更即A(A-B)A与 Git、Mercurial 的三方合并行为一致而与 Darcs 不同副作用是多次三方合并的结果可能依赖合并顺序第 124 行起的trivial_merge函数实现了平凡合并要求输入项数为奇数并针对最常见的 3 方合并[add0, remove, add1]做短路优化——当add0 add1且SameChange::Accept时直接返回add0。jj-converge设计文档正是建立在这些语义之上try_resolve_deduplicating_same_diffs被描述为与resolve_trivial相似但把多个相同的(X - Y)项只计数一次评审者可以对照core/src/merge.rs中的trivial_merge验证这一描述是否成立。在 Detailed Design 中引用这类核心抽象时应说明它们与现有语义的关系继承、扩展或修改这是评审能否通过的关键。编写设计文档的实践建议综合蓝图模板与仓库中的真实文档可以总结出以下经过验证的写作纪律先写 Summary 与 Goals/Non-Goals再写 Detailed Design。这两节是评审者最先读的部分也是争论最集中的部分每个应该都要有场景支撑。run.md的所有设计决策临时工作副本、保留 ignored 文件以支持增量构建、失败策略三选一都能追溯到 Use-Cases 或明确的问题陈述边界情况优先于主路径。jj-converge-command.md花大量篇幅处理候选父提交是分歧提交的后代演化历史超过 50 个节点等边缘情况并明确error out兜底用可验证的格式呈现行为。命令选项表、ASCII 提交图、Rust 结构体、伪代码函数这些格式在 jj 设计文档中被反复使用因为它们在评审中可以逐行讨论显式记录决策与遗留问题。run.md的 Open Points命令是否应工作副本后端相关如何管理进程配置选项是用户级还是仓库级、jj-converge-command.md的 Open questions是否会出现 committer 分歧改动 committer 是否安全都坦率地列出了未决问题——设计文档不是假装一切已定的文件链接要指向仓库内的相对路径。蓝图模板与各设计文档之间的交叉引用如git-submodules.md指向 docs/design/git-submodule-storage.md、design_docs.md指向 docs/design_doc_blueprint.md都应使用可从仓库根目录解析的相对路径确保评审者在 Web 界面上可以点击跳转如果特性涉及配置或命令对照配置样例验证。仓库中 cli/src/config/ 目录下的 TOML 样例如merge_tools.toml、revsets.toml与 cli/tests/sample-configs/ 中的配置测试可以作为设计文档中配置语法表述的实证来源。结语Jujutsu 的设计文档蓝图是一份最少骨架、最大自由的模板它不规定你必须写多少页但规定了必须回答的问题——现状是什么、目标与非目标是什么、接口长什么样、为什么不是别的方案、遗留了什么。仓库中docs/design/下的 9 篇设计文档从命令设计、数据模型重构到安全模型展示了这份蓝图在不同主题下的完整实践。当你准备为 jj 提交新特性时按蓝图搭建结构、以真实设计文档为参照、用源码语义支撑细节你的提案就具备了进入评审流程所需的全部要素。【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jj创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →