提交补丁:将代码纳入内核的基本指南

对于希望向 Linux 内核提交更改的个人或公司来说,如果不熟悉“系统”,这个过程有时可能会令人望而生畏。本文是建议的集合,可以大大增加您的更改被接受的机会。

本文档包含大量建议,格式相对简洁。有关内核开发过程工作方式的详细信息,请参阅内核开发流程指南。此外,在提交代码之前,请阅读Linux 内核补丁提交清单以获取要检查的项目列表。对于设备树绑定补丁,请阅读提交设备树 (DT) 绑定补丁

本文档假定您正在使用git来准备补丁。如果您不熟悉git,建议您学习如何使用它,这将使您作为内核开发人员的生活以及总体上变得更加轻松。

某些子系统和维护者树包含有关其工作流程和预期的额外信息,请参阅Documentation/process/maintainer-handbooks.rst

获取当前源代码树

如果您手头没有包含当前内核源代码的仓库,请使用git获取一个。您会希望从主线仓库开始,可以使用以下命令获取:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

但是请注意,您可能不希望直接针对主线树进行开发。大多数子系统维护者运行自己的树,并希望看到针对这些树准备的补丁。请参阅 MAINTAINERS 文件中子系统的 T: 条目以找到该树,如果该树未列出,则直接询问维护者。

描述您的更改

描述您的问题。无论您的补丁是一行错误修复还是 5000 行新功能,都必须有一个潜在问题促使您完成这项工作。说服评审者,这个问题值得修复,并且他们有理由阅读第一段之后的内容。

描述用户可见的影响。直接的崩溃和死锁非常有说服力,但并非所有错误都如此明显。即使在代码评审期间发现了问题,也要描述您认为它可能对用户产生的影响。请记住,大多数 Linux 安装运行的是来自辅助稳定树或特定供应商/产品的内核,这些内核仅从上游挑选特定补丁,因此请包含任何有助于将您的更改路由到下游的信息:触发情况、dmesg 摘录、崩溃描述、性能回退、延迟峰值、死锁等。

量化优化和权衡。如果您声称在性能、内存消耗、堆栈占用或二进制大小方面有所改进,请附上支持这些声明的数字。但也要描述不明显的成本。优化通常不是免费的,而是 CPU、内存和可读性之间的权衡;或者,当涉及到启发式方法时,是不同工作负载之间的权衡。描述您的优化预期的缺点,以便评审者可以权衡成本与收益。

问题确定后,详细描述您实际正在做的事情。用通俗易懂的语言描述更改很重要,以便评审者验证代码的行为是否符合您的预期。

如果您以易于拉入 Linux 源代码管理系统git作为“提交日志”的形式编写补丁描述,维护者会感谢您。请参阅标准补丁格式

每个补丁只解决一个问题。如果您的描述开始变得很长,那表明您可能需要拆分补丁。请参阅分离您的更改

当您提交或重新提交补丁或补丁系列时,请包含完整的补丁描述和理由。不要仅仅说这是补丁(系列)的第 N 个版本。不要指望子系统维护者会回溯到早期补丁版本或引用的 URL 来查找补丁描述并将其放入补丁中。也就是说,补丁(系列)及其描述应该是独立的。这有利于维护者和评审者。有些评审者可能甚至没有收到补丁的早期版本。

以祈使语气描述您的更改,例如“使 xyzzy 执行 frotz”,而不是“[此补丁] 使 xyzzy 执行 frotz”或“[我] 将 xyzzy 更改为执行 frotz”,就好像您正在命令代码更改其行为一样。

如果您想引用特定的提交,请不要只引用提交的 SHA-1 ID。请同时包含提交的一行摘要,以便评审者更容易了解其内容。例如:

Commit e21d2170f36602ae2708 ("video: remove unnecessary
platform_set_drvdata()") removed the unnecessary
platform_set_drvdata(), but left the variable "dev" unused,
delete it.

您还应确保至少使用 SHA-1 ID 的前十二个字符。内核仓库包含大量对象,因此与较短 ID 发生冲突的可能性很大。请记住,即使您的六字符 ID 现在没有冲突,五年后情况也可能会改变。

如果相关的讨论或更改背后的任何其他背景信息可以在网上找到,请添加指向它们的“Link:”标签。如果补丁是早期邮件列表讨论或网上记录的内容的结果,请指出它。

链接到邮件列表存档时,最好使用 lore.kernel.org 消息存档服务。要创建链接 URL,请使用邮件的Message-ID邮件头内容,不包括周围的尖括号。例如:

Link: https://lore.kernel.org/30th.anniversary.repost@klaava.Helsinki.FI

请检查链接,确保它实际有效并指向相关消息。

但是,请尝试在没有外部资源的情况下使您的解释易于理解。除了提供邮件列表存档或错误的 URL 外,还要总结导致提交补丁的讨论的相关要点。

如果您的补丁修复了一个错误,请使用“Closes:”标签,并附上引用邮件列表存档或公共错误跟踪器中报告的 URL。例如:

Closes: https://example.com/issues/1234

某些错误跟踪器能够在应用带有此类标签的提交时自动关闭问题。一些监控邮件列表的机器人也可以跟踪此类标签并采取某些操作。私人错误跟踪器和无效 URL 是禁止的。

如果您的补丁修复了特定提交中的错误,例如您使用git bisect发现了一个问题,请使用“Fixes:”标签,至少包含 SHA-1 ID 的前 12 个字符和一行摘要。不要将标签分成多行,标签不受“75 列换行”规则的限制,以简化解析脚本。例如:

Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")

以下git config设置可用于在git loggit show命令中输出上述样式的漂亮格式:

[core]
        abbrev = 12
[pretty]
        fixes = Fixes: %h (\"%s\")

一个示例调用

$ git log -1 --pretty=fixes 54a4f0239f2e
Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")

分离您的更改

将每个逻辑更改分成一个单独的补丁。

例如,如果您的更改包括对单个驱动程序的错误修复和性能增强,请将这些更改分成两个或更多补丁。如果您的更改包括 API 更新和使用新 API 的新驱动程序,请将它们分成两个补丁。

另一方面,如果您对多个文件进行单个更改,请将这些更改组合到一个补丁中。因此,单个逻辑更改包含在单个补丁中。

要记住的关键是每个补丁都应该进行易于理解的更改,并且可以由评审者验证。每个补丁都应该有其自身的价值。

如果一个补丁依赖于另一个补丁才能完成更改,那没关系。只需在您的补丁描述中注明“此补丁依赖于补丁 X”

将您的更改分成一系列补丁时,请特别注意确保内核在系列中的每个补丁之后都能正确构建和运行。使用git bisect来跟踪问题的开发人员最终可能会在任何时候拆分您的补丁系列;如果您在中间引入错误,他们将不会感谢您。

如果您无法将补丁集浓缩为更小的补丁集,那么每次只发布大约 15 个或更多,并等待评审和集成。

风格检查您的更改

检查您的补丁是否存在基本风格违规,详细信息可在Linux 内核编码风格中找到。不这样做只会浪费评审者的时间,并且您的补丁将被拒绝,可能甚至没有被阅读。

一个重要的例外是当代码从一个文件移动到另一个文件时——在这种情况下,您不应在移动代码的同一补丁中修改移动的代码。这清楚地划分了移动代码的行为和您的更改。这极大地有助于评审实际差异,并允许工具更好地跟踪代码本身的历史记录。

在提交之前使用补丁风格检查器(scripts/checkpatch.pl)检查您的补丁。但是请注意,风格检查器应被视为指导,而不是替代人工判断。如果您的代码在存在违规的情况下看起来更好,那么最好保持原样。

检查器报告三个级别:
  • ERROR:很可能错误的事项

  • WARNING:需要仔细评审的事项

  • CHECK:需要思考的事项

您应该能够解释补丁中所有剩余的违规。

选择补丁的接收者

您应始终将任何补丁抄送给其维护代码的相应子系统维护者和列表;查阅 MAINTAINERS 文件和源代码修订历史记录以了解这些维护者是谁。scripts/get_maintainer.pl脚本在此步骤中非常有用(将补丁路径作为参数传递给scripts/get_maintainer.pl)。如果您无法找到您正在处理的子系统的维护者,Andrew Morton (akpm@linux-foundation.org) 将作为最后一道防线维护者。

linux-kernel@vger.kernel.org应默认用于所有补丁,但该列表的邮件量已导致许多开发人员将其忽略。但是,请不要向不相关的列表和不相关的人员发送垃圾邮件。

许多与内核相关的列表托管在 kernel.org 上;您可以在https://subspace.kernel.org找到它们的列表。不过,也有在其他地方托管的与内核相关的列表。

Linus Torvalds 是所有被接受到 Linux 内核中的更改的最终仲裁者。他的电子邮件地址是 <torvalds@linux-foundation.org>。他收到很多电子邮件,而且,目前很少有补丁直接通过 Linus,所以通常您应该尽力 -避免- 给他发电子邮件。

如果您的补丁修复了可利用的安全漏洞,请将该补丁发送到security@kernel.org。对于严重漏洞,可以考虑短暂的禁令,以允许分发商将补丁提供给用户;在这种情况下,显然,补丁不应发送到任何公共列表。另请参阅安全漏洞

修复已发布内核中严重错误的补丁应通过在补丁的签名区域添加如下一行来发送给稳定版维护者:

Cc: stable@vger.kernel.org

到您的补丁的签名区域(注意,不是电子邮件收件人)。您除了阅读本文档外,还应该阅读您想了解的关于 Linux -stable 版本的一切

如果更改影响用户态-内核接口,请向 MAN-PAGES 维护者(在 MAINTAINERS 文件中列出)发送一个手册页补丁,或至少发送更改通知,以便一些信息能进入手册页。用户空间 API 更改也应抄送给linux-api@vger.kernel.org

回应评审意见

您的补丁几乎肯定会收到评审者关于如何改进补丁的评论,这些评论将以回复您电子邮件的形式出现。您必须回复这些评论;忽视评审者是反过来被忽视的好方法。您可以直接回复他们的电子邮件以回答他们的评论。那些不导致代码更改的评审评论或问题,几乎肯定应该带来一个评论或变更日志条目,以便下一个评审者更好地理解正在发生的事情。

务必告诉评审者您正在进行的更改,并感谢他们的时间。代码评审是一个耗时且费力的过程,评审者有时会变得脾气暴躁。即使在这种情况下,也要礼貌地回应并解决他们指出的问题。在发送下一个版本时,请在封面信或单个补丁中添加一个patch changelog,解释与之前提交的差异(参见标准补丁格式)。通过将他们添加到补丁的抄送列表中,通知对您的补丁发表评论的人有关新版本的信息。

有关电子邮件客户端和邮件列表礼仪的建议,请参阅Linux 电子邮件客户端信息

在电子邮件讨论中使用修剪过的交叉回复

在 Linux 内核开发讨论中,强烈不鼓励“顶层回复”。交叉(或“内联”)回复使对话更容易跟踪。欲了解更多详情,请参阅:https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

正如邮件列表中经常引用的那样:

A: http://en.wikipedia.org/wiki/Top_post
Q: Were do I find info about this thing called top-posting?
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing in e-mail?

同样,请修剪所有与您的回复无关的不必要引用。这使得查找回复更容易,并节省了时间和空间。欲了解更多详情,请参阅:http://daringfireball.net/2007/07/on_top

A: No.
Q: Should I include quotations after my reply?

不要气馁——或不耐烦

提交更改后,请耐心等待。评审者都很忙,可能不会立即处理您的补丁。

曾几何时,补丁常常无声无息地消失,但现在开发过程更加顺畅。您应该会在几周内(通常是 2-3 周)收到评论;如果未发生这种情况,请确保您已将补丁发送到正确的位置。在重新提交或“提醒”评审者之前,请至少等待一周——在合并窗口等繁忙时期可能需要更长时间。

也可以在几周后重新发送补丁或补丁系列,并在主题行中添加“RESEND”字样:

[PATCH Vx RESEND] sub/sys: Condensed patch summary

当您提交修改过的补丁或补丁系列版本时,不要添加“RESEND”——“RESEND”仅适用于与先前提交版本没有任何修改的补丁或补丁系列的重新提交。

在主题中包含 PATCH

由于 Linus 和 linux-kernel 邮件列表的邮件流量很大,通常约定在主题行前加上 [PATCH]。这让 Linus 和其他内核开发人员更容易将补丁与其他电子邮件讨论区分开来。

git send-email将自动为您完成此操作。

签署您的工作——开发者原创证书

为了更好地追踪谁做了什么,特别是对于那些可以通过多层维护者最终进入内核的补丁,我们引入了一个针对电子邮件传输补丁的“签署”程序。

签署是补丁解释末尾的一行简单文字,它证明了您编写了它,或者以其他方式有权将其作为开源补丁进行传递。规则很简单:如果您可以证明以下内容:

开发者原创证书 1.1

通过为本项目做出贡献,我证明:

  1. 本贡献全部或部分由我创建,我有权根据文件中指明的开源许可提交它;或者

  2. 本贡献基于先前的作品,据我所知,该作品受适当的开源许可保护,并且我有权根据该许可,在相同开源许可下(除非我被允许使用不同的许可)提交该作品及其修改(无论全部或部分由我创建),如文件中所示;或者

  3. 本贡献由其他已证明 (a)、(b) 或 (c) 的人直接提供给我,并且我未对其进行修改。

  4. 我理解并同意本项目和本贡献是公开的,并且贡献的记录(包括我提交的所有个人信息,包括我的签署)将无限期维护,并可根据本项目或所涉及的开源许可进行再分发。

那么您只需添加一行文字,表示:

Signed-off-by: Random J Developer <random@developer.example.org>

使用已知身份(抱歉,不接受匿名贡献)。如果您使用git commit -s,这将自动为您完成。回滚也应包含“Signed-off-by:”。git revert -s会为您完成此操作。

有些人也会在末尾添加额外的标签。这些标签目前将被忽略,但您可以使用它们来标记内部公司程序或指出有关签署的一些特殊细节。

任何在作者的 SoB 之后出现的其他 SoB (Signed-off-by:) 都来自处理和传输补丁的人员,但他们并未参与补丁的开发。SoB 链应反映补丁传播到维护者并最终传播到 Linus 的真实路径,其中第一个 SoB 条目表示单个作者的主要作者身份。

何时使用 Acked-by:、Cc: 和 Co-developed-by:

Signed-off-by: 标签表示签署人参与了补丁的开发,或者他/她处于补丁的交付路径中。

如果一个人没有直接参与补丁的准备或处理,但希望表示并记录他们对补丁的批准,那么他们可以要求在补丁的变更日志中添加 Acked-by: 行。

Acked-by: 旨在供以某种方式负责或参与受影响代码的人员使用。最常见的是,当维护者既没有贡献也没有转发补丁时,由维护者使用。

Acked-by: 也可由其他利益相关者使用,例如具有领域知识的人员(例如,被修改代码的原始作者)、内核 uAPI 补丁的用户空间侧评审者或功能的关键用户。可选地,在这些情况下,添加“# Suffix”以阐明其含义会很有用:

Acked-by: The Stakeholder <stakeholder@example.org> # As primary user

Acked-by: 不如 Signed-off-by: 正式。它记录了认可者至少已评审了补丁并表示接受。因此,补丁合并者有时会将认可者的“yep, looks good to me”手动转换为 Acked-by:(但请注意,通常最好请求明确的认可)。

Acked-by: 也不如 Reviewed-by: 正式。例如,维护者可以使用它来表示他们同意补丁的落地,但他们可能没有像提供 Reviewed-by: 那样彻底地评审它。同样,关键用户可能没有对补丁进行技术评审,但他们可能对总体方法、功能或用户界面感到满意。

Acked-by: 不一定表示对整个补丁的认可。例如,如果一个补丁影响多个子系统,并且有一个来自一个子系统维护者的 Acked-by:,那么这通常表示只认可影响该维护者代码的部分。这里需要进行判断。如有疑问,应参考邮件列表存档中的原始讨论。在这种情况下,也可以使用“# Suffix”来澄清。

如果一个人有机会对补丁发表评论,但没有提供此类评论,您可以选择在补丁中添加一个Cc:标签。此标签记录了潜在的利益相关方已参与讨论。请注意,这是您在未经命名人员明确许可的情况下可以使用的三个标签之一(有关详细信息,请参阅下文“标记人员需要权限”)。

Co-developed-by: 表示补丁由多位开发人员共同创建;当多人共同处理一个补丁时,它用于为共同作者(除了通过 From: 标签归属的作者)提供归属。由于 Co-developed-by: 表示作者身份,每个 Co-developed-by: 必须紧随其后的是相关共同作者的 Signed-off-by:。标准签署程序适用,即 Signed-off-by: 标签的顺序应尽可能反映补丁的时间历史,无论作者是通过 From: 还是 Co-developed-by: 归属的。值得注意的是,最后一个 Signed-off-by: 必须始终是提交补丁的开发人员。

请注意,当 From: 作者也是电子邮件头中的 From: 行中列出的人员(和电子邮件)时,From: 标签是可选的。

由 From: 作者提交的补丁示例

<changelog>

Co-developed-by: First Co-Author <first@coauthor.example.org>
Signed-off-by: First Co-Author <first@coauthor.example.org>
Co-developed-by: Second Co-Author <second@coauthor.example.org>
Signed-off-by: Second Co-Author <second@coauthor.example.org>
Signed-off-by: From Author <from@author.example.org>

由 Co-developed-by: 作者提交的补丁示例

From: From Author <from@author.example.org>

<changelog>

Co-developed-by: Random Co-Author <random@coauthor.example.org>
Signed-off-by: Random Co-Author <random@coauthor.example.org>
Signed-off-by: From Author <from@author.example.org>
Co-developed-by: Submitting Co-Author <sub@coauthor.example.org>
Signed-off-by: Submitting Co-Author <sub@coauthor.example.org>

使用 Reported-by:、Tested-by:、Reviewed-by:、Suggested-by: 和 Fixes:

Reported-by 标签用于表彰发现并报告错误的人员,并希望激励他们在未来再次帮助我们。此标签适用于错误;请不要用它来表彰功能请求。该标签后应跟一个指向报告的 Closes: 标签,除非报告在网络上不可用。如果补丁修复了所报告问题的一部分,则可以使用 Link: 标签代替 Closes:。请注意,Reported-by 标签是您在未经指定人员明确许可的情况下可以使用的三个标签之一(有关详细信息,请参阅下文“标记人员需要权限”)。

Tested-by: 标签表示补丁已由指定人员(在某种环境下)成功测试。此标签告知维护者已进行了一些测试,提供了一种在未来补丁中找到测试人员的方法,并确保对测试人员的功劳。

Reviewed-by: 则表示补丁已根据评审者声明进行评审并被认为可接受。

评审者的监督声明

通过提供我的 Reviewed-by: 标签,我声明:

  1. 我已对本补丁进行了技术评审,以评估其适合性和纳入主线内核的准备情况。

  2. 任何与补丁相关的问题、疑虑或疑问都已反馈给提交者。我对提交者对我评论的回应感到满意。

  3. 尽管本次提交可能还有改进之处,但我认为目前它(1)是对内核有价值的修改,并且(2)没有已知的会反对其纳入的问题。

  4. 尽管我已评审该补丁并认为其可靠,但我并不(除非另有明确说明)保证其能实现在任何给定情况下的既定目的或正常功能。

Reviewed-by 标签是一种意见声明,表示该补丁是对内核的适当修改,且没有剩余的严重技术问题。任何感兴趣的评审者(已完成工作)都可以为补丁提供 Reviewed-by 标签。此标签用于表彰评审者,并告知维护者对补丁已进行的评审程度。由已知理解主题领域并进行彻底评审的评审者提供的 Reviewed-by: 标签,通常会增加您的补丁被纳入内核的可能性。

Tested-by 和 Reviewed-by 标签,一旦从测试人员或评审者那里通过邮件列表收到,作者在发送下一个版本时应将其添加到适用的补丁中。但是,如果补丁在后续版本中发生了实质性变化,这些标签可能不再适用,因此应将其删除。通常,删除某人的 Tested-by 或 Reviewed-by 标签应在补丁变更日志中提及(在“---”分隔符之后)。

Suggested-by: 标签表示补丁的想法是由指定人员建议的,并确保对该想法的人员予以表彰:如果我们认真地表彰我们的想法报告者,他们有望在未来再次激励我们提供帮助。请注意,这是您在未经指定人员明确许可的情况下可以使用的三个标签之一(有关详细信息,请参阅下文“标记人员需要权限”)。

Fixes: 标签表示补丁修复了先前提交中的问题。它用于方便确定错误的来源,这有助于评审错误修复。此标签还帮助稳定版内核团队确定哪些稳定版内核版本应接收您的修复。这是指示补丁修复错误的推荐方法。有关更多详细信息,请参阅描述您的更改

注意:添加 Fixes: 标签不会颠覆稳定版内核规则流程,也不会免除在所有稳定版补丁候选上抄送stable@vger.kernel.org的要求。有关更多信息,请阅读您想了解的关于 Linux -stable 版本的一切

最后,虽然提供标签是受欢迎且通常非常受赞赏的,但请注意,签署人(即提交者和维护者)可以酌情使用所提供的标签。

标记人员需要权限

在您的补丁中添加上述标签时要小心,因为除了 Cc:、Reported-by: 和 Suggested-by: 之外的所有标签都需要指定人员的明确许可。对于这三个标签,如果该人员根据 lore 存档或提交历史记录使用该名称和电子邮件地址为 Linux 内核做出了贡献——并且在 Reported-by: 和 Suggested-by: 的情况下公开进行了报告或建议——则隐式许可就足够了。请注意,bugzilla.kernel.org 在此意义上是一个公共场所,但其中使用的电子邮件地址是私有的;因此,除非该人员在之前的贡献中使用了它们,否则不要在标签中暴露它们。

标准补丁格式

本节描述了补丁本身的格式。请注意,如果您的补丁存储在git仓库中,可以使用git format-patch获得正确的补丁格式。然而,这些工具无法创建必要的文本,因此无论如何请阅读以下说明。

主题行

标准补丁主题行是:

Subject: [PATCH 001/123] subsystem: summary phrase

标准补丁邮件正文包含以下内容:

  • 一行from,指定补丁作者,后跟一个空行(仅当发送补丁的人不是作者时才需要)。

  • 解释正文,行宽为 75 列,将复制到永久变更日志中以描述此补丁。

  • 一个空行。

  • 上述Signed-off-by:行,也将进入变更日志。

  • 一个仅包含---的标记行。

  • 任何不适合变更日志的额外评论。

  • 实际补丁(diff输出)。

主题行格式使得按主题行按字母顺序对电子邮件进行排序非常容易——几乎任何电子邮件阅读器都支持这一点——因为序列号是零填充的,所以数字排序和字母排序是相同的。

电子邮件主题中的subsystem应标识正在打补丁的内核区域或子系统。

电子邮件主题中的summary phrase应简洁地描述该电子邮件包含的补丁。summary phrase不应是文件名。不要对整个补丁系列中的每个补丁都使用相同的summary phrase(其中patch series是多个相关补丁的有序序列)。

请记住,您电子邮件的summary phrase成为该补丁的全球唯一标识符。它一直传播到git变更日志。summary phrase以后可能会在引用该补丁的开发人员讨论中使用。人们会希望通过谷歌搜索summary phrase来阅读有关该补丁的讨论。当两个或三个月后,他们使用gitkgit log --oneline等工具浏览数千个补丁时,它也将是他们可能迅速看到的唯一内容。

基于这些原因,summary长度必须不超过 70-75 个字符,并且必须描述补丁更改了什么以及为什么可能需要该补丁。既要简洁又要具描述性是一项挑战,但这正是编写良好的摘要应该做到的。

summary phrase可以在前面加上方括号括起来的标签:“Subject: [PATCH ...]

”。标签不被视为摘要短语的一部分,但描述了应如何处理补丁。常用标签可能包括版本描述符(如果针对评论发送了多个版本的补丁,即“v1、v2、v3”),或“RFC”以表示征求意见。

如果一个补丁系列中有四个补丁,则每个补丁可以这样编号:1/4、2/4、3/4、4/4。这确保开发人员了解补丁的应用顺序,并且他们已评审或应用了补丁系列中的所有补丁。

以下是一些好的主题示例:

Subject: [PATCH 2/5] ext2: improve scalability of bitmap searching
Subject: [PATCH v2 01/27] x86: fix eflags tracking
Subject: [PATCH v2] sub/sys: Condensed patch summary
Subject: [PATCH v2 M/N] sub/sys: Condensed patch summary

发件人行

from行必须是消息正文的第一行,其格式为:

From: Patch Author <author@example.com>

from行指定谁将在永久变更日志中被记为补丁的作者。如果from行缺失,则电子邮件头中的From:行将用于确定变更日志中的补丁作者。

作者可以通过在fromSoB行中添加组织名称来表明其所属或工作赞助商,例如:

From: Patch Author (Company) <author@example.com>

解释正文

解释正文将被提交到永久源代码变更日志中,因此对于一个有能力的读者来说应该有意义,即使他早已忘记了可能导致此补丁的讨论的即时细节。包含补丁解决的故障症状(内核日志消息、oops 消息等)对于可能正在搜索提交日志以查找适用补丁的人特别有用。文本应详细编写,以便在数周、数月甚至数年后阅读时,仍能为读者提供理解为什么创建此补丁所需的详细信息。

如果补丁修复了编译失败,可能不需要包含所有编译失败;只需包含足够的信息,以便搜索补丁的人很可能找到它。就像在summary phrase中一样,简洁和具描述性都很重要。

提交消息中的回溯信息

回溯信息有助于记录导致问题的调用链。然而,并非所有回溯信息都有用。例如,早期启动调用链是独一无二且显而易见的。但是,逐字复制完整的 dmesg 输出会添加分散注意力的信息,例如时间戳、模块列表、寄存器和堆栈转储。

因此,最有用的回溯信息应该从转储中提炼出相关信息,这使得更容易关注实际问题。以下是一个修剪良好的回溯信息的示例:

unchecked MSR access error: WRMSR to 0xd51 (tried to write 0x0000000000000064)
at rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20)
Call Trace:
mba_wrmsr
update_domains
rdtgroup_mkdir

评论

---标记行具有重要的作用,它为补丁处理工具标记了变更日志消息的结束位置。

---标记之后添加额外评论的一个好用途是提供diffstat,以显示哪些文件发生了更改,以及每个文件插入和删除的行数。diffstat对于较大的补丁特别有用。如果您要在---标记之后包含diffstat,请使用diffstat选项-p 1 -w 70,以便文件名从内核源代码树的顶部开始列出,并且不要占用过多水平空间(轻松适应 80 列,可能有一些缩进)。(git默认生成适当的 diffstats。)

其他仅与当前时刻或维护者相关,不适合永久变更日志的评论也应放在此处。此类评论的一个很好的例子可能是patch changelogs,它描述了补丁的 v1 和 v2 版本之间发生了什么变化。

请将此信息放在分隔变更日志与补丁其余部分的---之后。版本信息不属于提交到 git 树的变更日志。它是供评审者使用的额外信息。如果放在提交标签上方,则需要手动操作才能将其删除。如果放在分隔线下方,则在应用补丁时会自动将其删除。

<commit message>
...
Signed-off-by: Author <author@mail>
---
V2 -> V3: Removed redundant helper function
V1 -> V2: Cleaned up coding style and addressed review comments

path/to/file | 5+++--
...

有关正确补丁格式的更多详细信息,请参阅以下参考文献。

显式 In-Reply-To: 邮件头

手动为补丁添加 In-Reply-To: 邮件头(例如,当使用git send-email时)以将补丁与先前的相关讨论关联起来可能很有帮助,例如将错误修复链接到包含错误报告的电子邮件。但是,对于多补丁系列,通常最好避免使用 In-Reply-To: 链接到系列的旧版本。这样,补丁的多个版本就不会在电子邮件客户端中成为难以管理的引用森林。如果链接有帮助,您可以使用https://lore.kernel.org/重定向器(例如,在封面电子邮件正文中)链接到补丁系列的早期版本。

提供基础代码树信息

当其他开发人员收到您的补丁并开始评审过程时,他们绝对需要知道您的工作所基于的基础提交/分支是什么,考虑到当前维护者树的数量庞大。请再次注意上面解释的 MAINTAINERS 文件中的 T: 条目。

对于自动化 CI 流程而言,这一点更为重要,这些流程会尝试运行一系列测试,以在维护者开始评审之前确定您提交的质量。

如果您正在使用git format-patch生成补丁,您可以通过使用--base标志自动在提交中包含基础树信息。使用此选项最简单、最方便的方法是结合主题分支:

$ git checkout -t -b my-topical-branch master
Branch 'my-topical-branch' set up to track local branch 'master'.
Switched to a new branch 'my-topical-branch'

[perform your edits and commits]

$ git format-patch --base=auto --cover-letter -o outgoing/ master
outgoing/0000-cover-letter.patch
outgoing/0001-First-Commit.patch
outgoing/...

当您打开outgoing/0000-cover-letter.patch进行编辑时,您会注意到它会在最底部包含base-commit:尾部信息,这为评审者和 CI 工具提供了足够的信息,以便在不担心冲突的情况下正确执行git am

$ git checkout -b patch-review [base-commit-id]
Switched to a new branch 'patch-review'
$ git am patches.mbox
Applying: First Commit
Applying: ...

有关此选项的更多信息,请参阅man git-format-patch

注意

--base功能是在 git 2.9.0 版本中引入的。

如果您不使用 git 来格式化您的补丁,您仍然可以包含相同的base-commit尾部信息来指示您的工作所基于的树的提交哈希。您应该将其添加在封面信或系列中的第一个补丁中,并且它应该放在---行下方或所有其他内容的底部,紧邻您的电子邮件签名之前。

确保基础提交位于官方维护者/主线树中,而不是仅对您可访问的某个内部树中——否则它将毫无价值。

工具链

此过程的许多技术方面可以使用 b4 自动化,文档可在 <https://b4.docs.kernel.org/en/latest/> 找到。这有助于跟踪依赖项、运行 checkpatch 以及格式化和发送邮件等。

参考文献

Andrew Morton,“完美的补丁”(tpp)。

<https://www.ozlabs.org/~akpm/stuff/tpp.txt>

Jeff Garzik,“Linux 内核补丁提交格式”。

<https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>

Greg Kroah-Hartman,“如何惹恼内核子系统维护者”。

<http://www.kroah.com/log/linux/maintainer.html>

<http://www.kroah.com/log/linux/maintainer-02.html>

<http://www.kroah.com/log/linux/maintainer-03.html>

<http://www.kroah.com/log/linux/maintainer-04.html>

<http://www.kroah.com/log/linux/maintainer-05.html>

<http://www.kroah.com/log/linux/maintainer-06.html>

内核Linux 内核编码风格

Linus Torvalds 关于标准补丁格式的邮件

<https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>

Andi Kleen,“关于提交内核补丁”

提交困难或有争议更改的一些策略。

http://halobates.de/on-submitting-patches.pdf