提交补丁:将您的代码提交到内核的基本指南 【ChatGPT】

发布时间 2023-12-08 20:39:43作者: 摩斯电码

对于希望向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的前12个字符。内核存储库包含大量对象,使得较短的ID可能会发生冲突。请记住,即使现在您的六字符ID没有冲突,这种情况可能在五年后发生变化。

如果与更改相关的讨论或任何其他背后的信息可以在网络上找到,请添加指向它的“Link:”标签。如果补丁是由先前的邮件列表讨论或在网络上记录的某些内容产生的,请指向它。

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

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

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

但是,请尽量使您的解释在没有外部资源的情况下也能理解。除了给出邮件列表存档或错误的URL的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配置设置可用于在git log或git 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的新驱动程序,请将它们分成两个补丁。

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

需要记住的是,每个补丁应该进行一个易于理解的更改,审阅者可以验证。每个补丁应该有其自身的理由。

如果一个补丁依赖于另一个补丁才能完成更改,那是可以接受的。只需在您的补丁描述中注明“this patch depends on patch X”。

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

如果您无法将您的补丁集合缩减为更小的一组补丁,那么一次只发布15个左右的补丁,并等待审查和集成。

检查您的更改的样式

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

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

在提交之前,请使用补丁样式检查器(scripts/checkpatch.pl)检查您的补丁。但请注意,样式检查器应被视为指南,而不是人类判断的替代品。如果您的代码违反了规则但看起来更好,那最好还是不要修改。

检查器报告有三个级别:

  • 错误:很可能是错误的事情
  • 警告:需要仔细审查的事情
  • 检查:需要思考的事情

您应该能够证明您的补丁中所有违规都是合理的。

选择您的补丁的接收者

您应该始终将适当的子系统维护者和列表抄送到他们维护的任何代码的任何补丁中;请查看MAINTAINERS文件和源代码修订历史,以查看这些维护者是谁。脚本scripts/get_maintainer.pl在这一步骤中可能非常有用(将您的补丁的路径作为参数传递给scripts/get_maintainer.pl)。如果您找不到您正在工作的子系统的维护者,Andrew Morton(akpm@linux-foundation.org)是最后的维护者。

linux-kernel@vger.kernel.org应该默认用于所有补丁,但该列表的数量已经导致许多开发人员忽略了它。但请不要在无关的列表和无关的人员中发送垃圾邮件。

许多与内核相关的列表托管在vger.kernel.org上;您也可以在http://vger.kernel.org/vger-lists.html找到它们的列表。还有一些与内核相关的列表也托管在其他地方。

不要一次向vger邮件列表发送超过15个补丁!!!

Linus Torvalds是所有被接受到Linux内核的更改的最终仲裁者。他的电子邮件地址是torvalds@linux-foundation.org。他收到了大量的电子邮件,目前很少有补丁直接通过Linus,因此通常您应该尽量避免给他发送电子邮件。

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

修复已发布内核中的严重错误的补丁应通过在您的补丁的签名区域(注意,不是电子邮件接收者)中放置一行如下:

Cc: stable@vger.kernel.org

您还应该阅读《关于Linux -stable发布的一切》以及本文档。

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

没有MIME,没有链接,没有压缩,没有附件。只有纯文本。

Linus和其他内核开发人员需要能够阅读并评论您提交的更改。对于内核开发人员来说,能够使用标准的电子邮件工具“引用”您的更改非常重要,以便他们可以评论您代码的特定部分。

因此,所有补丁都应通过电子邮件“内联”方式提交。最简单的方法是使用git send-email,强烈建议使用。git send-email的交互式教程可在https://git-send-email.io上找到。

如果选择不使用git send-email:

警告
要小心编辑器的自动换行是否会破坏您的补丁,如果选择剪切和粘贴补丁。

不要将补丁作为MIME附件附加,无论是否压缩。许多流行的电子邮件应用程序并不总是将MIME附件传输为纯文本,这样就无法评论您的代码。MIME附件也会使Linus花费更多时间来处理,降低MIME附件更改被接受的可能性。

例外情况:如果您的邮件客户端破坏了补丁,那么有人可能会要求您使用MIME重新发送。

参见Linux的电子邮件客户端信息,了解如何配置您的电子邮件客户端,以便它以原样发送您的补丁。

回复审查意见

您的补丁几乎肯定会收到审阅者的评论,指出补丁可以改进的方式,以回复您的电子邮件形式。您必须回复这些评论;忽视审阅者是被忽视的好方法。您可以简单地回复他们的电子邮件以回答他们的评论。几乎肯定应该对不导致代码更改的审查评论或问题进行评论或更改日志条目,以便下一个审阅者更好地理解正在发生的事情。

一定要告诉审阅者您正在做出的更改,并感谢他们的时间。代码审查是一个疲惫且耗时的过程,审阅者有时会变得暴躁。即使在这种情况下,也要礼貌地回复并解决他们指出的问题。在发送下一个版本时,向封面信或单独的补丁添加一个补丁更改日志,解释与上一次提交的差异(参见规范的补丁格式)。

参见Linux的电子邮件客户端信息,了解电子邮件客户端和邮件列表礼仪的建议。

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

在Linux内核开发讨论中,强烈不建议顶部回复。交错(或“内联”)回复使对话更容易跟踪。更多详情请参见:https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

正如在邮件列表上经常引用的:

A: http://en.wikipedia.org/wiki/Top_post
Q: 我在哪里找到关于顶部回复的信息?
A: 因为它打乱了人们通常阅读文本的顺序。
Q: 为什么顶部回复是一件坏事?
A: 顶部回复。
Q: 电子邮件中最让人讨厌的是什么?

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

A: 不。
Q: 我的回复后是否应包含引用?

不要灰心或不耐烦

在提交您的更改后,请耐心等待。审阅者是忙碌的人,可能不会立即处理您的补丁。

曾经,补丁可能会消失在虚空中而没有评论,但现在的开发过程比那更加顺畅。您应该在一周左右内收到评论;如果没有收到,请确保您已将补丁发送到正确的位置。在重新提交或催促审阅者之前,请等待至少一周,可能在繁忙的时期(如合并窗口期间)更长时间。

在几周后,重新发送补丁或补丁系列时,在主题行中添加“RESEND”:

[PATCH Vx RESEND] sub/sys:压缩的补丁摘要

当您提交补丁或补丁系列的修改版本时,不要添加“RESEND” - “RESEND”仅适用于未经修改的补丁或补丁系列的重新提交。

在主题中包含PATCH

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

git send-email会自动为您执行此操作。

签署您的工作 - 开发者的原产地证书

为了更好地跟踪谁做了什么,特别是对于可能通过多层维护者最终到达内核的补丁,我们在通过电子邮件发送的补丁上引入了“签名”程序。

签名是在补丁说明的末尾的一行简单的内容,证明您编写了它或者以其他方式有权将其作为开源补丁传递。规则非常简单:如果您可以证明以下内容:

开发者的原产地证书1.1

通过向该项目做出贡献,我证明:

  • a. 该贡献全部或部分由我创建,并且我有权以文件中指示的开源许可证提交它;或
  • b. 该贡献基于我最好的知识,是基于适当的开源许可证覆盖的以前的工作,并且我有权根据该许可证提交该工作的修改,无论是全部还是部分由我创建;或
  • c. 该贡献是由其他人直接提供给我的,该人证明了(a)、(b)或(c),并且我没有对其进行修改。
  • d. 我理解并同意该项目和贡献是公开的,并且对贡献的记录(包括我提交的所有个人信息,包括我的签名)将被无限期地保留,并且可能根据该项目或涉及的开源许可证进行重新分发。

那么您只需添加一行:

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

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

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

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

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

Signed-off-by:标签表示签署者参与了补丁的开发,或者他/她在补丁的传递路径中。

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

当受影响代码的维护者既没有贡献也没有转发补丁时,通常会使用Acked-by:。Acked-by:不像Signed-off-by:那样正式。这是一个记录,表示批准者至少已经审查了补丁并表示接受。因此,补丁合并者有时会手动将批准者的“是的,看起来不错”转换为Acked-by:(但请注意,最好要求明确的批准)。

Acked-by:并不一定表示对整个补丁的确认。例如,如果一个补丁影响多个子系统,并且其中一个子系统的维护者已经确认了,那么这通常表示只确认了影响该维护者代码的部分。在这里应该使用判断。当有疑问时,人们应该参考邮件列表档案中的原始讨论。

如果一个人有机会对补丁进行评论,但没有提供这样的评论,您可以选择向补丁添加一个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:作者提交的补丁示例:

<更改日志>

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>

<更改日志>

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)没有已知的问题会反对其纳入。

  • 虽然我已经审查了这个补丁并认为它是合理的,但我不会(除非在其他地方明确说明)提供任何保证或担保,以确保它能够实现其所述的目的或在任何给定的情况下正常运行。

"Reviewed-by" 标签是对补丁是内核的一个适当修改且没有严重技术问题的意见陈述。任何感兴趣的审阅者(已经完成了工作的)都可以为补丁提供 "Reviewed-by" 标签。此标签用于给予审阅者荣誉,并通知维护者对补丁已进行的审查程度。由了解主题领域并进行彻底审查的审阅者提供的 "Reviewed-by" 标签通常会增加您的补丁进入内核的可能性。

一旦从测试者或审阅者的邮件列表中收到 "Tested-by" 和 "Reviewed-by" 标签,作者在发送下一个版本时应将这些标签添加到适用的补丁中。但是,如果在随后的版本中补丁发生了重大变化,这些标签可能不再适用,因此应予以删除。通常应在补丁更改日志中提及删除某人的 "Tested-by" 或 "Reviewed-by" 标签(在 '---' 分隔符之后)。

"Suggested-by" 标签表示该补丁的想法是由指定的人提出的,并确保为该想法的人给予了荣誉。请注意,特别是如果该想法没有在公共论坛上发布,不应添加此标签而未经报告者的许可。也就是说,如果我们认真给予我们的想法报告者荣誉,他们将有希望在将来再次帮助我们。

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

注意:附加 "Fixes" 标签不会规避稳定内核规则流程,也不会规避在所有稳定补丁候选项上抄送 stable@vger.kernel.org 的要求。有关更多信息,请阅读《您想知道的有关 Linux -stable 发行版的一切》。

规范的补丁格式

本节描述了补丁本身应该如何格式化。请注意,如果您的补丁存储在 git 存储库中,可以使用 git format-patch 来获得适当的补丁格式。但是,这些工具无法创建必要的文本,因此无论如何请阅读下面的说明。

规范的补丁主题行是:

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

规范的补丁消息正文包含以下内容:

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

  • 说明的正文,每行最多 75 个字符,这将被复制到永久的更改日志中,以描述此补丁。

  • 一个空行。

  • 如上所述的 Signed-off-by: 行,这也将进入更改日志。

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

  • 任何不适合更改日志的其他评论。

  • 实际的补丁(diff 输出)。

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

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

邮件主题中的摘要短语应该简洁地描述该邮件包含的补丁。摘要短语不应该是文件名。不要在整个补丁系列中的每个补丁中使用相同的摘要短语(其中补丁系列是多个相关补丁的有序序列)。

请记住,您的电子邮件的摘要短语成为该补丁的全局唯一标识符。它传播到 git 更改日志。摘要短语可能会在以后用于开发人员讨论中引用该补丁。人们将希望通过摘要短语进行谷歌搜索,以阅读有关该补丁的讨论。当人们在两三个月后使用 gitk 或 git log --oneline 等工具查看数千个补丁时,它也将是人们可能快速看到的唯一内容。

因此,摘要必须不超过 70-75 个字符,并且必须同时描述补丁的更改以及为什么可能需要该补丁。既简洁又描述性是具有良好撰写的摘要应该做的事情。

摘要短语可以用方括号括起来的标签前缀:"Subject: [PATCH <tag>...] <summary phrase>"。标签不被视为摘要短语的一部分,但描述了应该如何处理该补丁。常见的标签可能包括版本描述符(如果对评论发送了多个版本的补丁,即 "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: 行来确定更改日志中的补丁作者。

说明正文将提交到永久的源更改日志中,因此应该对长期以来已经忘记了可能导致此补丁的讨论的细节的能力的读者有意义。包括补丁解决的故障的症状(内核日志消息、oops 消息等)对于可能正在搜索适用补丁的人特别有用。文本应该写得非常详细,以便在几周、几个月甚至几年后阅读时,可以为读者提供所需的细节,以理解为什么创建了该补丁的原因。

如果一个补丁修复了编译失败,可能不需要包括所有的编译失败;只需要足够多的内容,以便可能正在搜索补丁的人能够找到它。与摘要短语一样,既简洁又描述性是非常重要的。

--- 标记行的主要目的是标记补丁处理工具在哪里结束更改日志消息。

在 --- 标记之后的其他评论的一个很好的用途是 diffstat,以显示哪些文件已更改,以及每个文件的插入和删除行数。对于更大的补丁,diffstat 尤其有用。如果您要在 --- 标记之后包含 diffstat,请使用 diffstat 选项 -p 1 -w 70,以便文件名从内核源树的顶部列出,并且不占用太多水平空间(很容易适合 80 列,也许有一些缩进)。 (git 默认生成适当的 diffstat。)

仅与当时或维护者相关的其他评论,不适合永久更改日志,也应该放在这里。这样的评论的一个很好的例子可能是描述 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+++--
...

有关适当的补丁格式的更多详细信息,请参阅以下参考资料。

提交信息中的回溯

回溯有助于记录导致问题的调用链。然而,并非所有的回溯都是有用的。例如,早期引导调用链是独特且明显的。然而,直接复制完整的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

显式的In-Reply-To头部

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

提供基本树信息

当其他开发人员收到您的补丁并开始审查过程时,了解他们应该将您的工作放在树历史的哪个位置通常是有用的。这对于尝试在维护者开始审查之前运行一系列测试以确定您提交的质量的自动化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: trailer,这为审阅者和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 trailer,以指示您的工作所基于的树的提交哈希。您应该将其添加到---行下方或所有其他内容的底部,就在您的电子邮件签名之前。

参考资料

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

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

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

不要再向linux-kernel@vger.kernel.org的人发送大量补丁!

内核Linux内核编码风格

Linus Torvalds关于规范补丁格式的邮件:

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