.. include:: ../disclaimer-zh_CN.rst

:Original: :ref:`Documentation/process/7.AdvancedTopics.rst <development_advancedtopics>`

:Translator:

 时奎亮 Alex Shi <alex.shi@linux.alibaba.com>

:校译:

 吴想成 Wu XiangCheng <bobwxc@email.cn>

.. _cn_development_advancedtopics:

高级主题
========

现在，希望您能够掌握开发流程的工作方式。然而，还有更多的东西要学！本节将介绍
一些主题，这些主题对希望成为Linux内核开发过程常规部分的开发人员有帮助。

使用Git管理补丁
---------------

内核使用分布式版本控制始于2002年初，当时Linus首次开始使用专有的Bitkeeper应用
程序。虽然BitKeeper存在争议，但它所体现的软件版本管理方法却肯定不是。分布式
版本控制可以立即加速内核开发项目。现在有好几种免费的BitKeeper替代品。
但无论好坏，内核项目都已经选择了Git作为其工具。

使用Git管理补丁可以使开发人员的生活更加轻松，尤其是随着补丁数量的增长。Git也
有其粗糙的边角和一定的危险性，它是一个年轻和强大的工具，仍然在其开发人员完善
中。本文档不会试图教会读者如何使用git；这会是个巨长的文档。相反，这里的重点
将是Git如何特别适合内核开发过程。想要加快用Git速度的开发人员可以在以下网站上
找到更多信息：

	https://git-scm.com/

	https://www.kernel.org/pub/software/scm/git/docs/user-manual.html

同时网上也能找到各种各样的教程。

在尝试使用它生成补丁供他人使用之前，第一要务是阅读上述网页，对Git的工作方式
有一个扎实的了解。使用Git的开发人员应能进行拉取主线存储库的副本，查询修订
历史，提交对树的更改，使用分支等操作。了解Git用于重写历史的工具（如rebase）
也很有用。Git有自己的术语和概念；Git的新用户应该了解引用、远程分支、索引、
快进合并、推拉、游离头等。一开始可能有点吓人，但这些概念不难通过一点学习来
理解。

使用git生成通过电子邮件提交的补丁是提高速度的一个很好的练习。

当您准备好开始建立Git树供其他人查看时，无疑需要一个可以从中拉取的服务器。
如果您有一个可以访问因特网的系统，那么使用git-daemon设置这样的服务器相对
简单。同时，免费的公共托管网站（例如github）也开始出现在网络上。成熟的开发
人员可以在kernel.org上获得一个帐户，但这些帐户并不容易得到；更多有关信息，
请参阅 https://kernel.org/faq/ 。

正常的Git工作流程涉及到许多分支的使用。每一条开发线都可以分为单独的“主题
分支”，并独立维护。Git的分支很容易使用，没有理由不使用它们。而且，在任何
情况下，您都不应该在任何您打算让其他人从中拉取的分支中进行开发。应该小心地
创建公开可用的分支；当开发分支处于完整状态并已准备好时(而不是之前）才合并
开发分支的补丁。

Git提供了一些强大的工具，可以让您重写开发历史。一个不方便的补丁（比如说，
一个打破二分法的补丁，或者有其他一些明显的缺陷）可以在适当的位置修复，或者
完全从历史中消失。一个补丁系列可以被重写，就好像它是在今天的主线上写的一样，
即使你已经花了几个月的时间在写它。可以透明地将更改从一个分支转移到另一个
分支。等等。明智地使用git修改历史的能力可以帮助创建问题更少的干净补丁集。

然而，过度使用这种功能可能会导致其他问题，而不仅仅是对创建完美项目历史的
简单痴迷。重写历史将重写该历史中包含的更改，将经过测试（希望如此）的内核树
变为未经测试的内核树。除此之外，如果开发人员没有共享项目历史，他们就无法
轻松地协作；如果您重写了其他开发人员拉入他们存储库的历史，您将使这些开发
人员的生活更加困难。因此，这里有一个简单的经验法则：被导出到其他地方的历史
在此后通常被认为是不可变的。

因此，一旦将一组更改推送到公开可用的服务器上，就不应该重写这些更改。如果您
尝试强制进行无法快进合并的更改（即不共享同一历史记录的更改），Git将尝试强制
执行此规则。这可能覆盖检查，有时甚至需要重写导出的树。在树之间移动变更集以
避免linux-next中的冲突就是一个例子。但这种行为应该是罕见的。这就是为什么
开发应该在私有分支中进行（必要时可以重写）并且只有在公共分支处于合理的较新
状态时才转移到公共分支中的原因之一。

当主线（或其他一组变更所基于的树）前进时，很容易与该树合并以保持领先地位。
对于一个私有的分支，rebasing 可能是一个很容易跟上另一棵树的方法，但是一旦
一棵树被导出到外界，rebasing就不可取了。一旦发生这种情况，就必须进行完全
合并（merge）。合并有时是很有意义的，但是过于频繁的合并会不必要地扰乱历史。
在这种情况下建议的做法是不要频繁合并，通常只在特定的发布点（如主线-rc发布）
合并。如果您对特定的更改感到紧张，则可以始终在私有分支中执行测试合并。在
这种情况下，git“rerere”工具很有用；它能记住合并冲突是如何解决的，这样您
就不必重复相同的工作。

关于Git这样的工具的一个最大的反复抱怨是：补丁从一个存储库到另一个存储库的
大量移动使得很容易陷入错误建议的变更中，这些变更避开审查雷达进入主线。当内
核开发人员看到这种情况发生时，他们往往会感到不高兴；在Git树上放置未审阅或
主题外的补丁可能会影响您将来让树被拉取的能力。引用Linus的话:

::

   你可以给我发补丁，但当我从你那里拉取一个Git补丁时，我需要知道你清楚
   自己在做什么，我需要能够相信事情而 *无需* 手动检查每个单独的更改。

（http://lwn.net/Articles/224135/）。

为了避免这种情况，请确保给定分支中的所有补丁都与相关主题紧密相关；“驱动程序
修复”分支不应更改核心内存管理代码。而且，最重要的是，不要使用Git树来绕过
审查过程。不时的将树的摘要发布到相关的列表中，在合适时候请求linux-next中
包含该树。

如果其他人开始发送补丁以包含到您的树中，不要忘记审阅它们。还要确保您维护正确
的作者信息； git “am”工具在这方面做得最好，但是如果补丁通过第三方转发给您，
您可能需要在补丁中添加“From:”行。

请求拉取时，请务必提供所有相关信息：树的位置、要拉取的分支以及拉取将导致的
更改。在这方面 git request-pull 命令非常有用；它将按照其他开发人员所期望的
格式化请求，并检查以确保您已记得将这些更改推送到公共服务器。

审阅补丁
--------

一些读者显然会反对将本节与“高级主题”放在一起，因为即使是刚开始的内核开发人员
也应该审阅补丁。当然，没有比查看其他人发布的代码更好的方法来学习如何在内核环境
中编程了。此外，审阅者永远供不应求；通过审阅代码，您可以对整个流程做出重大贡献。

审查代码可能是一副令人生畏的图景，特别是对一个新的内核开发人员来说，他们
可能会对公开询问代码感到紧张，而这些代码是由那些有更多经验的人发布的。不过，
即使是最有经验的开发人员编写的代码也可以得到改进。也许对（所有）审阅者最好
的建议是：把审阅评论当成问题而不是批评。询问“在这条路径中如何释放锁？”
总是比说“这里的锁是错误的”更好。

不同的开发人员将从不同的角度审查代码。部分人会主要关注代码风格以及代码行是
否有尾随空格。其他人会主要关注补丁作为一个整体实现的变更是否对内核有好处。
同时也有人会检查是否存在锁问题、堆栈使用过度、可能的安全问题、在其他地方
发现的代码重复、足够的文档、对性能的不利影响、用户空间ABI更改等。所有类型
的检查，只要它们能引导更好的代码进入内核，都是受欢迎和值得的。
