Bitcoin Core 贡献者指南:从提交补丁到 Peer Review 的完整工作流
本文以 Bitcoin Core 仓库根目录的 CONTRIBUTING.md 为主体,完整梳理该项目"开放贡献者模型"下的协作规范:如何提交原子化的 commit、如何撰写符合规范的 Pull Request(PR)标题与正文、squash 与 rebase 的实操命令、Peer Review 的术语体系(Concept (N)ACK / Approach (N)ACK / ACK BRANCH_COMMIT),以及合并判定、共识级补丁的额外要求和 backport 元数据格式。读完本文,你可以按项目维护者的标准独立完成一个可被合并的 PR,并理解其背后的 git 历史卫生原则。
一、开放贡献者模型:没有特权开发者
Bitcoin Core 采用开放贡献者模型(open contributor model):任何人都可以通过同行评审(peer review)、测试和补丁三种形式参与开发。项目并不存在"特权开发者"的概念——开源社区通常是靠贡献者随时间赢得信任而自然形成的 meritocracy(贤者政治)。
但从实践管理角度,仍需要一定的层级结构:仓库维护者(repository maintainers)负责合并 pull request、执行发布周期(release cycle,见 发布流程)和社区管理。这意味着:
- 贡献入口对所有开发者平等;
- 但代码进入
master的"最后一公里"由维护者把关,评审与测试正是普通贡献者影响这个把关过程的主要渠道。
1.1 新贡献者的最佳切入点
文档明确指出:深入的评审和测试是整个项目的瓶颈,也是任何人开始贡献时最有效的方式。相比直接开 PR,先做评审和测试能让你对代码和流程学到更多,还可能帮助你发现相关问题和后续可以贡献代码的跟进点。
开始贡献前,建议先熟悉 Bitcoin Core 的构建系统和测试体系。当前仓库中对应的资料与代码位置:
| 内容 | 仓库位置 |
|---|---|
| 开发者编码规范(C++ 风格、测试结构、加锁约定等) | doc/developer-notes.md |
| 单元测试(Boost.Test) | src/test/(约 300 个 .cpp 文件) |
| 功能测试(Python 集成测试) | test/functional/(300+ 测试脚本,规范见 test/functional/README.md) |
| Fuzz 测试文档(libFuzzer / AFL++ / Honggfuzz) | doc/fuzzing.md |
| CI 测试脚本(容器化测试矩阵) | ci/test/、ci/README.md |
| Lint 检查(rust-based linter 等) | ci/lint/、test/lint/ |
| PR 评审俱乐部 | 官方组织的 PR Review Club(Bitcoin Core 社区活动) |
1.2 AI 工具使用政策
如果贡献过程中使用了 AI 工具,必须阅读并遵守 AI 政策。核心要求包括:
- 禁止用 AI 生成与维护者/其他贡献者交流的评论,评论必须由人撰写,疑似 AI 生成的评论可能被 moderation;
- 提交 PR 的前提是:你了解代码所用语言、你自己有能力写出这段代码、理解周边既有代码和所提议变更的影响;
- 必须能用自己的话解释 PR 的变更,包括 PR 正文和对 reviewer 提问的回复,不得复制 AI 的回答去回复 reviewer 的提问;
- 项目要求有"人在环"(human author in the loop):PR 不应由自主 Agent 打开或驱动,commit 中也不要把 agent 列为作者或共同作者;违反此条的 PR 可能被无预警关闭。
二、沟通渠道
围绕 Bitcoin Core 开发的沟通主要通过以下渠道进行:
- IRC:Libera Chat 的
#bitcoin-core-dev频道是开发讨论的主要场所,有 web 客户端可直接参与,也有第三方聊天历史存档可查; - GitHub issues 与 pull requests:代码库改进的讨论在此进行;
- bitcoindev 邮件列表:复杂的或有争议的共识规则(consensus)或 P2P 协议变更,在动手写补丁之前应先在此列表上讨论(列表有公开存档)。
渠道选择的实践含义是:普通的 bugfix、重构走 GitHub 即可;一旦你的改动触碰共识规则,未先在邮件列表充分讨论的补丁很难通过评审(详见第六节的决策流程)。
三、贡献者工作流:fork → 分支 → 提交 → PR
代码库采用"contributor workflow"维护:所有人无一例外都通过 pull request 提交补丁提案。这种方式便于社会化协作、测试和同行评审。
3.1 基本流程
- Fork 仓库(仅在第一次贡献时);
- 创建主题分支(topic branch);
- 提交补丁(committing patches,见 3.3 节);
- 将变更推送到你的 fork;
- 创建 pull request(见 3.4 节)。
对 PR 作者有三条硬性要求(来自文档原文的归纳):
- 必须完全且有把握地理解自己的变更,并且已经测试过;
- 应说明哪些测试覆盖了本次变更,或列出你用于确认变更的手动步骤;
- 应准备好清晰地说明并解释变更的动机;若评审者有疑虑,PR 可能被直接关闭。
3.2 monotree:GUI 与 Node 仓库的划分
当前 Bitcoin Core 采用"monotree"(单树多仓库)组织:GUI 相关的问题或 PR 使用 bitcoin-core/gui 仓库,其余所有问题和 PR 使用 bitcoin/bitcoin(node)仓库,两个仓库的 master 分支内容完全一致。
默认判据:只修改 src/qt 的改动属于 GUI-only PR。但有以下三个例外:
- 全局重构或其他横向(transversal)改动 → 走 node 仓库;
- GUI 相关的构建系统改动 → 走 node 仓库,因为这类变更需要构建系统 reviewer 的评审(对应本仓库中的 CMakeLists.txt、cmake/ 等文件);
- 修改
src/interfaces的变更 → 走 node 仓库,因为这些接口可能影响钱包等其他组件(对应本仓库的 src/interfaces/、src/common/interfaces.cpp)。
对于同时包含构建系统与接口改动的大型 GUI 变更,推荐的分步策略是:先在 GUI 仓库开 PR 达成方向共识,再把构建系统与接口的变更提交到 node 仓库。
项目编码规范必须遵循 developer notes。
3.3 提交补丁(Committing Patches)
原子性与可读性。commit 应当是原子的(atomic commit convention),diff 应当易读。因此:
- 不要把格式修复、代码移动与真正的代码改动混在同一个 commit 里;
- 每个单独的 commit 必须是"卫生的"(hygienic):能独立构建成功,无警告、无错误、无回归、无测试失败。
commit 结构中的测试归属:文档引用 developer notes 的 "Commit Structure for Tests" 一节,其具体规则是:
- 若已有测试覆盖了被修改的行为,应在同一 commit 中更新这些测试(diff 同时记录新旧期望值);
- 简单的功能或 bugfix 没有既有覆盖时,变更与测试通常可以在同一个 commit;
- 非平凡的 refactor,若相关不变量还没有自动化测试,先在单独的测试 commit 中加入覆盖,refactor commit 本身就不需要改动测试期望;
- 对既有行为的非平凡修改若无覆盖,考虑加一个前置的 characterization test commit,并用
TODO注释标记那些期望值会随行为改变而变化的断言。
commit message 规范(默认应详尽):
- 短标题行(最长 50 字符)+ 空行 + 详细的解释性段落;
- 例外:仅当标题本身就自解释时(如 "Correct typo in init.cpp"),单行标题即可;
- 消息要面向未来读代码的人,解释你做各项决策的理由;
- 若某个 commit 关联其他 issue,请加上引用,例如
refs #1234或fixes #4321。使用fixes或closes关键字会在 PR 合并时自动关闭对应 issue; - commit message 中永远不要出现
@提及(@username)。
PR 之外的两个实操技巧(来自 生产力笔记,与 squash 工作流直接相关):
# 在 "dummy rebase" 上用 autosquash 收纳 fixup commit,
# 而不必在更新的 master 上 rebase(避免引入无关冲突):
git rebase -i --autosquash "$(git merge-base master HEAD)"
# 对自 diverge 点以来每个 commit 自动跑构建与单测:
git rebase -i --exec "cmake --build build && ctest --test-dir build" "$(git merge-base master HEAD)"
3.4 创建 Pull Request
标题前缀必须标明 PR 影响的组件或区域。合法的 area 前缀完整列表如下:
| 前缀 | 适用范围 |
|---|---|
consensus |
共识关键(consensus critical)代码变更 |
doc |
文档变更 |
qt 或 gui |
bitcoin-qt 变更 |
log |
日志消息变更 |
mining |
挖矿代码变更 |
net 或 p2p |
P2P 网络代码变更 |
refactor |
不改变行为的重构 |
rpc、rest 或 zmq |
RPC、REST 或 ZMQ API 变更 |
contrib 或 cli |
脚本和工具变更 |
test、qa 或 ci |
单元测试、QA 测试或 CI 代码变更 |
util 或 lib |
工具库(utils)或库变更 |
wallet |
钱包代码变更 |
build |
CMake 变更 |
guix |
Guix 可复现构建变更 |
官方给出的标题示例:
consensus: Add new opcode for BIP-XXXX OP_CHECKAWESOMESIG
net: Automatically create onion service, listen on Tor
qt: Add feed bump button
log: Fix typo in log message
正文要求:
- 必须充分描述补丁做了什么,更要为什么,并给出理由与论证;
- 应引用相关讨论(其他 issue 或邮件列表讨论);
- 新建 PR 的正文中不得包含任何
@提及。原因:PR 描述在合并时会并入 merge commit 的 commit message,每个 fork 该 commit 时,被提及的用户都会被反复通知。用户名提及应放在 PR 的后续评论中。
翻译变更:翻译不应以 PR 形式提交。流程见 翻译流程:翻译通过 Transifex 管理,src/qt/locale/ 下的源文件由自动化脚本更新(如用 cmake --preset dev-mode 构建后 --target translate 重新生成 bitcoin_en.ts),普通 PR 不应包含翻译源文件的更新,以避免合并冲突并在发布前留出翻译时间。
WIP 与 RFC 标记:若 PR 暂不考虑合并,标题前加 [WIP],或在正文中使用 GitHub 的 Tasks Lists 标记待办任务。
3.5 处理评审反馈
PR 提交后应预期收到其他贡献者的评论与评审。你可以本地新增 commit 并推送到 fork,从而给 PR 追加 commit。
- 在 PR 被合并前,你被期望回复所有评审评论;
- 你可以修改代码,也可以不同意反馈而拒绝,但必须在回复中明确表达;
- 若存在悬而未决的反馈而你未在处理,PR 可能被关闭。
3.6 Squash Commits
若 PR 中含有 fixup commit(反复修改同一行代码的 commit)或粒度过细的 commit,可能在你获得评审之前就被要求先 squash。官方给出的基本工作流:
git checkout your_branch_name
git rebase -i HEAD~n
# n 通常是 PR 中 commit 的数量。
# 将第一行之外的 commit 从 'pick' 改为 'squash',保存并退出。
# 在下一个屏幕上编辑/润色 commit message。
# 保存并退出。
git push -f # (force push 到 GitHub)
Squash 后如需更新 commit message,应使其读起来像一条连贯的消息——大多数情况下意味着不是简单罗列中间 commit。
注意:若分支中含 merge commit,上述工作流可能不生效,需要先移除 merge commit(见下一节的 rebase)。
另外两条纪律:
- 不要为同一变更开多个 PR;用已打开(或更早创建)的 PR 来修正变更,这保留了针对该变更集的既有讨论与评审;
- Peer review 所需时间不可预测,因 PR 而异。
3.7 Rebase Changes
当 PR 与目标分支冲突时,可能被告知其 rebase 到当前目标分支顶部:
git fetch https://github.com/bitcoin/bitcoin # Fetch the latest upstream commit
git rebase FETCH_HEAD # Rebuild commits on top of the new base
生产力笔记 提供了单 PR 的更精细做法(不必拉全量数据):
# 单独 fetch 某个 PR
git fetch upstream pull/<number>/head
# fetch 并切到本地分支
git fetch upstream pull/<number>/head:pr-<number> && git switch pr-<number>
Rebase 后,评审者被鼓励对 force push 进行 sign-off(复核)。生产力笔记 中介绍的 git range-diff 工具(Git >= 2.19)用于"diff of diffs":当贡献者 rebase 或修改非头部的 commit 后 force push,reviewer 无法仅凭 commit hash 判断之前的评审是否仍然有效,git range-diff master previously-reviewed-head new-head 可以直接对比新旧两个 commit 范围的 patch 差异,从而高效完成复核。为避免无谓的评审损耗(review churn),维护者通常会优先合并那些获得最多评审关注的 PR。
3.8 干净的 git 历史与签名验证
项目追求干净的 git 历史:代码变更只出现在非 merge commit 中。这简化了可审计性——merge commit 可以假定不携带任意代码变更;merge commit 必须签名,且其产生的 git tree hash 必须是确定且可复现的。
仓库中 contrib/verify-commits/ 的脚本负责检查这一点。其 README 说明了配套机制:
verify-commits.py是一个 Python 3 脚本,对照trusted-keys(受信 PGP 指纹列表)验证 commit 签名;- 配置文件包括
trusted-git-root(信任根:第一个未签名 commit 的哈希)、trusted-sha512-root-commit、trusted-keys、allow-revsig-commits(因签名密钥过期/吊销而需豁免的 commit 列表); - 使用前需先用
gpg导入受信密钥; - 一个重要安全细节:不能用不受信的脚本来验证自身——先 checkout 代码再对
HEAD跑verify-commits.py是不安全的(脚本本身可能已被植入后门)。正确的顺序是先 fetch,用受信版本的verify-commits.py验证origin/master,再 checkout,例如:
git fetch origin && \
./contrib/verify-commits/verify-commits.py origin/master && \
git checkout origin/master
除非指定 --clean-merge 0,verify-commits.py 还会验证每个 merge commit 是否干净应用(要求至少 git v2.38.0)。
四、PR 哲学:聚焦,避免"超大 PR"
补丁集(patchset)应当始终聚焦:一个 PR 可以加功能、修 bug、或做重构,但不能三者混杂。同时要避免"super pull requests"——试图做太多、过大或过于复杂的 PR,因为其评审难度极高。
4.1 新功能
增加新功能必须考虑其长期技术债与维护成本。提议一个需要维护的新功能前,先考虑你是否愿意维护它(包括修 bug)。如果未来某个功能成为"孤儿"(无人维护),它可能被仓库维护者移除。
4.2 重构
重构是项目演进不可避免的一部分,规范将其分为三类:
- 代码移动(code-only moves);
- 代码风格修复(code style fixes);
- 代码重构(code refactoring)。
三条铁律:
- 重构 PR 不应混合这三类活动,以便评审容易且无争议;
- 任何情况下,重构 PR 都不得改变代码行为(bug 必须原样保留,"bugs must be preserved as is");
- 维护者追求对重构 PR 的快速周转,因此尽量短、不复杂、易验证;
- 新贡献者不应提交重构类 PR——判断代码"该放在哪"并理解全部影响(包括对其他打开 PR 的 rebase 代价)需要一定经验;
- 明显琐碎、或没有清晰收益的重构 PR,维护者可能直接关闭以减轻评审负担。
五、Peer Review:术语体系与评审深度
任何人可以参与 peer review,评审以 PR 评论表达。reviewer 通常检查明显的错误、实际跑一遍补丁集、并对技术价值发表意见。维护者在判断是否达到合并共识时会综合考虑 peer review(注意:讨论可能分散在 GitHub、邮件列表和 IRC 三处)。
5.1 评审成本的经济学
代码评审是繁重但重要的一环,因此某类 PR 会被直接拒绝:一般地,如果改进的收益不足以抵消所需的评审成本,PR 被拒绝的概率很高。PR 作者有责任说服 reviewer 变更值得这份评审成本;若 reviewer 在"概念上 NACK"你的 PR,作者可能需要摆出论据、甚至做研究来支撑自己的提议。
此外,若有合理理由怀疑 PR 作者不完全理解自己提交的变更,或明显自己都没做过基本测试,PR 可能被立即关闭。
5.2 概念评审(Conceptual Review)
两种表达:
Concept (N)ACK:"我(不)同意这个 PR 的总体目标";Approach (N)ACK:Concept ACK但"我(不)同意这个变更的实现路径"。
NACK 必须附带理由,解释为什么该变更不值得做;没有理由的 NACK 可被忽视。
5.3 代码评审(Code Review)
在概念达成一致后,才开始代码评审。评审以 ACK BRANCH_COMMIT 开始,其中 BRANCH_COMMIT 是 PR 分支的顶部 commit,随后附评审者说明自己如何完成的评审。PR 评论中的惯用语:
- "I have tested the code":除了跑单元/功能/fuzz 测试外,还做了变更相关的手动测试;若手动测试方式不明显,应描述出来;
- "I have not tested the code, but I have reviewed it and it looks OK, I agree it can be merged":只做了代码审读而未实际运行测试;
- "nit":琐碎的、通常非阻塞的问题。
评审权重规则:
- 维护者保留用常识判断权衡各评审意见的权利,也可以基于 merit(贡献深度)加权;
- 随时间展现出更深的投入与理解、或有明确领域专长的 reviewer,其意见自然更重——这是所有行业的常态;
- 触碰共识关键代码(包括对共识关键代码的重构)的补丁集,讨论与 peer review 门槛会大幅提高,因为错误对更广泛社区的代价可能极高;
- 提议改变 Bitcoin 共识的补丁集,必须:已在邮件列表和 IRC 充分讨论、有被广泛讨论的编号 BIP、并且维护者判断社区对"这是一个有价值的变更"形成了普遍的技术共识。
5.4 找不到 reviewer 怎么办
多数 reviewer 本身也是有自己项目的开发者,评审过程可能相当漫长,需要耐心。若 PR 数月无人问津,文档给出五种排查思路:
- 可能正值 feature freeze(临近发布的特性冻结期):期间只考虑 bug fix,新功能 PR 不会优先处理——等发布结束即可;
- 变更本身可能不受欢迎:与其"沉默如雷"(thundering silence)相对,nit 和批评反而说明有人在认真对待你的贡献。沉默是对变更的普遍(轻度)不喜欢的良好信号。不要个人化,而是重新审视自己的提议是否:改动太多、太宽泛、不符合 developer notes、危险或不安全、写得凌乱。找出并解决这些问题后,可以在 IRC 上请人评价"概念本身";
- 代码可能太复杂以至于只有少数人懂,而他们甚至不知道这个 PR 存在:用 GitHub 的 Git Blame 功能查最后修改你正在改的代码的人,找到并礼貌地"轻推"(nudge)他们——但不要不停刷屏;
- 最后兜底:直接在 IRC 或别处请求有人看一眼你的 PR。若你认为等待了不合理的时长(比如超过一个月)且没有特别原因(如只改了几行代码),这么做完全没问题。同时,当别人请求反馈你的代码时记得"还人情",社区会自我平衡;
- 等待期间最好的事是去给别人做评审。
六、决策流程("Decision Making" Process)
以下规则适用于 Bitcoin Core 项目(以及相关项目如 libsecp256k1)的代码变更,不要将其与比特币网络层面的协议共识变更混淆。PR 是否合并由项目 merge 维护者决定,他们综合考虑:补丁是否符合项目总体原则、是否达到入库的最低标准、以及贡献者群体的普遍共识。
所有 PR 必须满足:
- 有清晰的使用场景,修复可复现的 bug,或服务项目整体利益(例如面向模块化的重构);
- 经过良好的 peer review;
- 在适用处具备单元测试、功能测试和 fuzz 测试(对应本仓库的 src/test/、test/functional/ 与 fuzz 目标,fuzz 构建与运行见 doc/fuzzing.md);
- 遵循代码风格规范(C++ 风格见 developer notes,功能测试风格见 test/functional/README.md);
- 不破坏既有测试套件;
- 修复 bug 时,在可能处应有展示该 bug 的单元测试并证明修复有效,以防止回归;
- 行为变化时同步更新相关注释与文档。
共识规则变更远比普通补丁复杂,因为它影响整个生态系统:必须先经过邮件列表的大量讨论并配有编号 BIP;每种情况都不同,但应当预期付出比其他方式更多的时间与精力(评审与共识构建要求都更高)。
七、Backport:回移植的元数据规范
安全修复与 bug fix 可以从 master 回移植(backport)到 release 分支。维护者会批量执行回移植,并在需要时使用正确的 Needs backport (...) 标签(原作者无需操心)。
backport commit 的正文必须包含以下元数据:
Github-Pull: #<PR number>
Rebased-From: <commit hash of the original commit>
此外,官方还提到:可参考历史 backport PR 实例,以及 bitcoin-maintainer-tools 仓库中的 backport.py 脚本(位于项目外部的 maintainer 工具仓库,本文不展开)。
八、版权与许可证
向本仓库贡献即表示同意:除非 contrib/debian/copyright 或文件顶部另有说明,否则你的作品以 MIT 许可证授权(对应仓库根的 COPYING 文件)。凡由你贡献但并非原创的作品,必须包含其许可证头,注明原作者与来源。这与全仓库源码文件头部普遍出现的 Distributed under the MIT software license, see the accompanying file COPYING 注释保持一致。
九、快速核对清单(Pre-Submission Checklist)
把以上规范压缩成提交前的自检清单:
- 改动是否单一聚焦?格式化/移动与行为变更是否拆开了?每个 commit 独立可构建、无警告、无测试失败?
- commit 标题 ≤50 字符、正文解释了"为什么"、无
@提及?测试按 developer notes 的 commit 结构规则放对了位置? - PR 标题带了正确的 area 前缀(对照第三节的 14 类前缀表)?正文说明了 what + why + 测试依据,且无
@提及? - 只改
src/qt之外还碰了构建系统或src/interfaces?→ 确认应走 node 仓库。 - 若等待 rebase:
git fetch+git rebase FETCH_HEAD,force push 后用 range-diff 帮助 reviewer 复核;若需 squash,按git rebase -i HEAD~n工作流合并并改写连贯的 commit message。 - 涉及共识关键代码或共识规则?→ 先确认已有邮件列表讨论与 BIP,评审门槛相应提高。
- 若使用了 AI 工具:确认符合 AI_POLICY.md,所有对外沟通均为人工撰写,commit 作者中无 agent。
以上流程与仓库中的实际工程设施(CMake 构建体系、ci/test/ 的多平台测试矩阵、contrib/verify-commits/ 的签名验证、doc/productivity.md 的评审效率工具)共同构成了 Bitcoin Core 高质量协作的完整闭环:贡献者按原子 commit 与聚焦 PR 提交,社区按 Concept/Approach/Code 三层评审过滤,维护者按可复现的签名历史合并,最终形成一条"每个 merge commit 都可审计"的 master 分支。
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 StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00