Flirt:GitHub 和邮件列表后端
摘要
Flirt 是一个代码审查工具,现已实现新的 GitHub 和邮件列表后端,并计划不久后开源以获取早期反馈。
<p><a href="https://lobste.rs/s/scwuwv/flirt_github_mailing_list_backends">评论</a></p>
查看缓存全文
缓存时间: 2026/08/15 13:43
# Flirt:GitHub 与邮件列表后端
来源:https://blog.buenzli.dev/flirt-github-and-mailing-list
这是 Flirt 开发进展的更新。先前文章:
- 宣布开发 Flirt (https://blog.buenzli.dev/announcing-development-on-flirt)
- Flirt:原生后端 (https://blog.buenzli.dev/flirt-native-backend)
距离上次发布已有一段时间。此前我专注于论文撰写,并于 8 月 1 日提交完成 🥳
我已让评论线程基本运作起来,并实现了 GitHub 和邮件列表的后端支持。这些功能目前存在局限且在某些方面尚不稳定,但我认为通过一定努力可以克服。
接下来,我将清理代码并准备将 Flirt 开源。虽然暂时还不适合**普通用户**,但对那些认同我代码审查理念、希望从早期参与 Flirt 开发的人来说会很有价值。我计划在 1-2 个月内完成此事。
继续阅读以了解 GitHub 和邮件列表后端的技术细节!
## 本地存储 (https://blog.buenzli.dev/flirt-github-and-mailing-list#local-storage)
原生后端因 Git 工作机制必须将所有内容存储在本地。你需要从远程拉取 Spirit,在本地处理后再次推送。目前我为其他后端也采用了相同的自定义引用机制。如果每次操作都要调用 GitHub API 或下载邮件线程会非常繁琐。这些自定义引用会保留在本地,仅在用户请求与后端同步时才转换为 API 调用或邮件发送。
## GitHub PR 的历史提交 (https://blog.buenzli.dev/flirt-github-and-mailing-list#past-submissions-of-github-prs)
GitHub 最大的问题是你无法获取 PR 的历史强制推送信息。这意味着 Flirt 无法展示所有提交版本间的差异对比。实际应用中问题不大:用户通常只关心之前观察过的提交。标准用例是对比「上次评审的版本」与「当前版本」的差异。这基本可以正常运作,因为系统会在本地记录上次评审的版本。
需注意:
- 切换工作站可能导致问题。如果新工作站从未获取过「上次评审版本」,将无法通过 GitHub API 轻易获取。
- API 会显示评论针对的确切提交哈希值。理论上可借此重建历史提交,但会产生边界情况:若评论针对「中间」提交而非 PR 分支的最新提交,系统只能部分重建提交历史。实现该功能可能引入更多复杂情况。
GitHub 的评审界面会展示 PR 或提交的差异供评论,而 Flirt 则在代码库的特定状态上添加评论,假设用户通过常规版本控制工具查看差异。问题在于 Flirt 无法在差异的左侧(删除行)添加评论。由此产生疑问:应将评论置于何处?在右侧差异中寻找「相似位置」并不可取,因为上下文可能完全不同。
我目前能想到的中短期最佳解决方案是:将删除行的上下文作为「标题头」附加到包含线程的评论块中。这样上下文始终与线程关联。线程可置于删除行附近的「相似位置」,或创建为仅评审工作流一部分的特殊文件。
但我认为这仍不理想。反复思考这个问题后,我开始确信:仅查看代码的某个状态、并以 Git HEAD 代表先前状态是不够的。能在实际差异文件中直接输入评论逐渐成为合理且重要的用例。这可能成为 Flirt 支持的第二种「模式」,或是融合两者优势的混合工作流。无论如何,实现这些功能可能需要一定时间。
## public-inbox:开源邮件列表存档 (https://blog.buenzli.dev/flirt-github-and-mailing-list#public-inbox-the-open-source-mailing-list-archive)
邮件列表是个抽象概念,无法直接支持。实际上我了解的开源项目都使用 public-inbox (https://github.com/nojb/public-inbox) 托管邮件列表存档,包括 Linux 内核和 Git 项目。
目前我仅选择支持使用 public-inbox 的项目。若有其他重要项目采用不同方案,请告知!我很乐意探索支持它们所需的工作量。
## git format-patch 输出中缺失的信息 (https://blog.buenzli.dev/flirt-github-and-mailing-list#missing-information-in-git-format-patch-output)
构建在邮件列表之上的评审工具,最佳「标准」格式是 git format-patch 的输出。遗憾的是,它对 Flirt 的用例而言仍有欠缺。
### 基础提交 (https://blog.buenzli.dev/flirt-github-and-mailing-list#base-commit)
git format-patch 可自动添加基础提交信息,但默认不启用。用户需通过 `--base` 标志主动请求。若缺失基础提交信息,Flirt 应如何处理?将补丁应用到 HEAD 还是 master?无论哪种选择在某些情况下都会出错并引发冲突。我们可以让评审者手动指定基础版本,但这在用户体感上很不理想。理想情况下,评审者应要求补丁系列作者使用 `--base` 重新提交。
Jujutsu 将其变更标识存储在自定义提交头中,但 git format-patch 不会保留这些信息。此前 Git 邮件列表有相关提案 (https://lore.kernel.org/git/[email protected]/) 但未被采纳。
若缺失变更标识头,Flirt 最重要的功能将无法可靠运行。虽然可实现基于主题行、作者等信息的启发式匹配,但 git range-diff 已尝试通过补丁相似性解决此问题。在现有约束下,Flirt 最终只能采用某种启发式方法。
Flirt 对 Spirit 及其提交有相对严格的模型,但这与邮件列表机制不完全契合。git format-patch 可在主题行添加版本标签,规范的补丁系列提交通常呈现如下格式:
- `[PATCH v1 0/N] add some feature`
- `[PATCH v2 0/N] add some feature`
- `[PATCH v3 0/N] add some feature`
若主题行足够明确以区别于其他所有补丁系列,即可用于确定 Spirit 的所有提交版本。但用户可能遗忘版本标签或修改文本描述。
根据项目规范,检测相关版本有更可靠的方式。Git 项目建议每个补丁系列的第一封邮件应作为前一版本提交的首封邮件回复。如此所有提交可构成完整的邮件线程。示例如下:
```
[PATCH v1 0/3] add feature
├── [PATCH v1 1/3] implement feature
├── [PATCH v1 2/3] test feature
├── [PATCH v1 3/3] document feature
│
└── [PATCH v2 0/3] add feature
├── [PATCH v2 1/3] implement feature
├── [PATCH v2 2/3] test feature
├── [PATCH v2 3/3] document feature
│
└── [PATCH v3 0/3] add feature
├── [PATCH v3 1/3] implement feature
├── [PATCH v3 2/3] test feature
└── [PATCH v3 3/3] document feature
```
这对 Flirt 非常友好,也是我当前选择支持的格式。未来可实现备用启发式方案。
遗憾的是,该实践并未广泛普及。Linux 内核文档明确建议不采用此方式 (https://docs.kernel.org/process/submitting-patches.html#explicit-in-reply-to-headers):
> 然而,对于多补丁系列,通常应避免使用 In-Reply-To: 链接到该系列的早期版本。这样可以避免邮件客户端中出现难以管理的引用关系森林。
读到此处我不禁思考:「如果为绕过技术局限而故意省略清晰相关的结构化信息,这是否恰恰表明你所用的技术并不适合该任务?」
### 读写评论 (https://blog.buenzli.dev/flirt-github-and-mailing-list#reading-and-writing-comments)
邮件列表中的典型「评论线程」如下所示:
```
>> +fn foo() {
>> + println!("foo")
>> +}
>
> I think this function could be implemented more efficiently.
Which concrete optimizations do you suggest?
```
如你所料,将其解析为结构化格式相当繁琐。虽非高难度技术,但存在大量边界情况:
- 线程不必通过直接回复邮件延续。引用早期邮件中的文本是允许的。
- 评论者可引用非线程原始内容的文本。这并非对现有线程的回复,仅是引用。
- 评论者常缩略编辑其回复的上下文。*理想情况下*,此类评论仍应被识别为现有线程的一部分。或许可以尝试基于常见缩写符 `[...]` 分割引用,并在现有线程中搜索这些子字符串?
目前我仅实现了非常简单的场景。
发送评论邮件相对容易。Flirt 只需遵守基本规范。目前新评论的前驱评论会被引用为上下文。若前驱评论过长,用户可能希望缩略后再发送邮件,但目前暂不支持。
实际上,Flirt 并不发送真实邮件。它只是构造邮件并将其管道传输至 `public-inbox-mda`,以导入本地测试的 public-inbox 实例。经过更多测试后,实际发送这些邮件应该不难。(对吧?)
## 总结 (https://blog.buenzli.dev/flirt-github-and-mailing-list#conclusion)
以上是我目前能汇报的所有技术思考。下次你听到我的消息时,Flirt 应当已经开源。此外,我今年将参加 JJ Con (https://git-merge.com/)。欢迎来打招呼 🙂
相似文章
@github:GitHub 最新动态?GitHub Copilot 现已登陆 Slack 和 Microsoft Teams,新增模型可用,代码审查引入新功能……
GitHub 八月更新包括 Copilot 集成至 Slack 与 Microsoft Teams、新增 Gemini 3.7 Flash 和 Kimi K3 等 AI 模型、增强代码审查功能,同时推出促销定价及社区活动。
共同打造更健康的Clippy
Rust Clippy团队宣布一项新举措,以解决维护者倦怠和审查瓶颈问题:审查他人PR的贡献者将优先获得自身PR的审查。此举措灵感来自Bevy的‘开放代码审查’系统。
Cursor 准备推出代码审查平台 Origin(2 分钟阅读)
Cursor 正准备推出 Origin,这是一个带有 Codebase 和 Review 标签页的代码审查平台,可实现自动化拉取请求管道,以支持人类与智能体协作。该平台由被收购的 Graphite 团队打造,最早可能于本周上线。
Flare
Flare 是一款专为智能体编程设计的图优先集成开发环境(IDE)和交互式地图,旨在简化开发工作流程。
Flare:一个图优先的代理编码IDE:观察图谱在代理工作时变化
Flare是一个开源桌面IDE,它将代码库可视化为实时图谱,并通过实时更新、影响范围分析以及为AI代理集成任务管理来增强代理编码。