Beads `bd diff` 使用指南:对比任意两个提交或分支间的 issue 变更
bd diff 是 Beads 提供的版本对比命令,用于展示两个提交或分支之间 issue(事务项)的差异,支持 commit 哈希、分支名与 HEAD 等特殊引用。本文以 docs/cli-reference/diff.md 为骨架,结合仓库源码深入讲解命令的参数规则、输出格式、底层 Dolt dolt_diff() 实现与测试验证方式,帮助你完成分支评审、版本回溯与变更审计。
命令定位与基本用法
bd diff 隶属于 views 命令组,是一条只读的视图类命令,位于 cmd/bd/diff.go。其完整用法为:
bd diff <from-ref> <to-ref> [flags]
命令要求恰好两个位置参数(源码中通过 cobra.ExactArgs(2) 强制校验,cmd/bd/diff.go),分别表示对比的起点引用与终点引用。官方文档给出的三个典型示例:
bd diff main feature-branch # 对比 main 与 feature 分支
bd diff HEAD~5 HEAD # 查看最近 5 次提交引入的变更
bd diff abc123 def456 # 对比两个具体提交
docs/cli-reference/diff.md 是命令行文档体系的一部分,由 bd help --doc diff 自动生成(文件头部标注了 AUTO-GENERATED 说明),因此它与 cmd/bd/diff.go 中 diffCmd 的 Long 描述保持一致,可作为命令行为的权威依据。
支持的三类引用(ref)
文档明确规定,from-ref 与 to-ref 可以是以下三类值:
| 引用类型 | 示例 | 说明 |
|---|---|---|
| 提交哈希(commit hash) | abc123def、abc123 |
定位到某个具体提交的快照 |
| 分支名(branch name) | main、feature-branch |
定位到分支当前所指向的提交 |
| 特殊引用 | HEAD、HEAD~1 |
Git/Dolt 风格的相对与指针引用 |
在底层,两个引用会先经过 ValidateRef 校验(internal/storage/issueops/as_of.go):引用不能为空、长度不得超过 128 字符,且只能匹配正则 ^<a href="https://link.gitcode.com/i/91f138f95d1fe8c15e7e6e64d554b03a" target="_blank">a-zA-Z0-9_./-]+$。这意味着分支名可以包含点号和斜杠,例如 release/v2.0、feature/auth.flow 这类命名都能通过校验;而包含空格或特殊符号的非法输入会被拒绝。该校验同时服务于 dolt_diff() 表函数,因为 Dolt 要求把 ref 作为 SQL 字符串字面量内联进查询(不接受预处理绑定参数),严格的字符白名单是防止 SQL 注入的关键防线,这一点在 [internal/storage/dolt/versioned.go 的注释中有明确说明。
输出格式详解
命令执行成功后,输出会根据是否有变更而呈现两种形态;同时支持 --json 标志切换为结构化输出。
无变更提示
当两个引用之间没有任何 issue 发生变化时,直接输出一行提示:
No changes between <from-ref> and <to-ref>
对应源码分支见 cmd/bd/diff.go。
人类可读输出
存在变更时,命令先打印变更统计行,再按 added、modified、removed 三种类型分组展示(cmd/bd/diff.go):
- Added(新增):以
+前缀展示新 issue 的 ID 与标题; - Modified(修改):以
~前缀展示 issue ID,并额外标注发生了变化的字段,可能组合出现title(标题)、status: open -> done(状态流转)、priority: P1 -> P2(优先级变更)、description(描述)等; - Removed(删除):以
-前缀展示被删除 issue 的 ID 与原标题。
字段差异的判定逻辑位于 cmd/bd/diff.go:分别比较 OldValue 与 NewValue 的 Title、Status、Priority、Description 四个字段,凡是不同的字段都会被列入变化清单。
JSON 输出
配合全局 --json 标志,bd diff 会直接输出一个 DiffEntry 数组(cmd/bd/diff.go),每条记录包含 IssueID、DiffType 以及可选的 OldValue/NewValue,非常适合脚本化处理与 CI 集成:
bd diff main feature-branch --json
DiffEntry 结构定义在 internal/storage/versioned.go:DiffType 取值 "added"、"modified"、"removed";OldValue 在 added 时为 nil,NewValue 在 removed 时为 nil。
底层实现:Dolt 的 dolt_diff() 表函数
bd diff 的核心计算并不在 CLI 层,而是委托给存储层完成。命令入口调用 store.Diff(ctx, fromRef, toRef)(cmd/bd/diff.go),在 Dolt 后端由 DoltStore.Diff 在一个只读事务中执行(internal/storage/dolt/versioned.go),最终落到 issueops.DiffInTx(internal/storage/issueops/diff.go):
SELECT
COALESCE(from_id, '') as from_id,
COALESCE(to_id, '') as to_id,
diff_type,
from_title, to_title,
from_description, to_description,
from_status, to_status,
from_priority, to_priority
FROM dolt_diff('<from-ref>', '<to-ref>', 'issues')
其要点如下:
- 使用 Dolt 内建的
dolt_diff(from, to, table)表函数直接对 issues 表的两个快照 做差异比对; diff_type由 Dolt 给出,取值即added/modified/removed;- 通过
COALESCE(from_id, to_id)提取行的标识 ID(新增行没有from_id,删除行没有to_id),这一手法在 internal/storage/issueops/diff.go 中用于组装DiffEntry.IssueID; - 注意从源码注释可以推断:
dolt_diff(from, to, table)对比的是两个快照之间的差异,并不会逐条遍历中间提交(见 internal/storage/dolt/versioned.go 对同类查询的说明)。也就是说,即使某个 issue 在区间内被删除后又重建,只要它在终点快照存在,就会归入added/modified而非removed。
值得说明的是,仓库中还实现了另一个更高层的 ChangedIssueIDs 方法(internal/storage/dolt/versioned.go),它通过 UNION ALL 把 issues、labels、dependencies、comments 四张表的 dolt_diff 结果合并,服务于自动导出场景。这印证了 Beads 对"变更检测"的需求不止于 issues 主表本身——标签、依赖、评论的改动同样会被纳入视野。
模式限制与注意事项
- Proxied-server 模式不支持:
bd diff在检测到代理服务器模式(usesProxiedServer())时会直接报错diff is not supported in proxied-server mode(cmd/bd/diff.go),因此该命令仅在嵌入式存储等直接模式下可用; - 引用合法性前置校验:两个 ref 参数在进入 SQL 前都会经过
ValidateRef,非法字符或过长的输入会得到明确报错; - 错误信息输出:命令自身设置
SilenceUsage与SilenceErrors,并统一经由HandleErrorRespectJSON处理错误,这意味着在--json模式下错误也会以 JSON 形式返回,便于自动化消费; - 遥测:每次执行会记录一个
metrics.NewCommandEvent("diff")事件(cmd/bd/diff.go),用于统计命令使用情况。
测试验证与典型工作流
bd diff 的 CLI 行为在 cmd/bd/diff_embedded_test.go 中有完整的嵌入式集成测试覆盖,测试辅助函数包括:
bdDiff:执行bd diff <args>并断言成功;bdDiffFail:执行后断言失败(用于验证非法 ref、错误模式等场景);bdDiffJSON:追加--json标志执行并把输出解析为 JSON 数组,验证结构化输出的正确性。
实际工作中,bd diff 可以与其他视图类命令配合形成完整的工作流:
- 提交前用
bd diff HEAD~1 HEAD快速自检最近一次改动的范围; - 合入分支前用
bd diff main feature-branch评审待合入的变更集合; - 需要查看单个 issue 的完整演进历史时,配合 bd history(按 issue 维度回溯每次提交的快照);
- 需要定位到某一次具体变更的内容时,用 bd show 查看某条 issue 的当前状态,再结合
bd diff判断从何时开始变化; - 完整命令清单与分组(
views组)可参考 CLI 参考索引,而 Beads 面向 agent 的总体能力说明见 README.md。
小结
bd diff 把 Dolt 底层的版本快照对比能力封装成了一条极简的双参数命令:文档层面的三类 ref 规则、三种变更类型分组、字段级差异标注与 JSON 输出,配合源码中 ValidateRef 的安全校验、dolt_diff() 的 SQL 实现以及嵌入式集成测试,构成了一个既可人工评审、又可脚本化消费的完整 diff 能力。需要对比两个分支或提交间的 issue 变更时,bd diff <from-ref> <to-ref> 就是最直接的入口。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.21 K637- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python270
cherry-studio🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端TypeScript2 K146
hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程Python46066
new-apiAI模型聚合管理中转分发系统,一个应用管理您的所有AI模型,支持将多种大模型转为统一格式调用,支持OpenAI、Claude、Gemini等格式,可供个人或者企业内部管理与分发渠道使用。🍥 A Unified AI Model Management & Distribution System. Aggregate all your LLMs into one app and access them via an OpenAI-compatible API, with native support for Claude (Messages) and Gemini formats.Go20143
JeecgBoot🔥企业级低代码平台集成了AI应用平台,帮助企业快速实现低代码开发和构建AI应用!前后端分离架构 SpringBoot,SpringCloud、Mybatis,Ant Design4、 Vue3.0、TS+vite!强大的代码生成器让前后端代码一键生成,无需写任何代码! 引领AI低代码开发模式: AI生成->OnlineCoding-> 代码生成-> 手工MERGE,显著的提高效率,又不失灵活~Java34051