.. SPDX-License-Identifier: GPL-2.0

.. include:: ../disclaimer-zh_TW.rst

:Original: :ref:`Documentation/process/5.Posting.rst <development_posting>`

:Translator:

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

:校譯:

 吳想成 Wu XiangCheng <bobwxc@email.cn>
 胡皓文 Hu Haowen <src.res@email.cn>

.. _tw_development_posting:

發布補丁
========

您的工作遲早會準備好提交給社區進行審查，並最終包含到主線內核中。毫不稀奇，
內核開發社區已經發展出一套用於發布補丁的約定和過程；遵循這些約定和過程將使
參與其中的每個人的生活更加輕鬆。本文檔試圖描述這些約定的部分細節；更多信息
也可在以下文檔中找到
:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`，
:ref:`Documentation/translations/zh_TW/process/submitting-drivers.rst <tw_submittingdrivers>`
和 :ref:`Documentation/translations/zh_TW/process/submit-checklist.rst <tw_submitchecklist>`。

何時郵寄
--------

在補丁完全「準備好」之前，避免發布補丁是一種持續的誘惑。對於簡單的補丁，這
不是問題。但是如果正在完成的工作很複雜，那麼在工作完成之前從社區獲得反饋就
可以獲得很多好處。因此，您應該考慮發布正在進行的工作，甚至維護一個可用的Git
樹，以便感興趣的開發人員可以隨時趕上您的工作。

當發布中有尚未準備好被包含的代碼，最好在發布中說明。還應提及任何有待完成的
主要工作和任何已知問題。很少有人會願意看那些被認爲是半生不熟的補丁，但是
那些願意的人會帶著他們的點子來一起幫助你把工作推向正確的方向。

創建補丁之前
------------

在考慮將補丁發送到開發社區之前，有許多事情應該做。包括：

 - 儘可能地測試代碼。利用內核的調試工具，確保內核使用了所有可能的配置選項組合
   進行構建，使用交叉編譯器爲不同的體系結構進行構建等。

 - 確保您的代碼符合內核代碼風格指南。

 - 您的更改是否具有性能影響？如果是這樣，您應該運行基準測試來顯示您的變更的
   影響（或好處）；結果的摘要應該包含在補丁中。

 - 確保您有權發布代碼。如果這項工作是爲僱主完成的，僱主對這項工作具有所有權，
   並且必須同意根據GPL對其進行發布。

一般來說，在發布代碼之前進行一些額外的思考，幾乎總是能在短時間內得到回報。

補丁準備
--------

準備補丁發布的工作量可能很驚人，但在此嘗試節省時間通常是不明智的，即使在短期
內亦然。

必須針對內核的特定版本準備補丁。一般來說，補丁應該基於Linus的Git樹中的當前
主線。當以主線爲基礎時，請從一個衆所周知的發布點開始——如穩定版本或 -rc
版本發布點——而不是在一個任意的主線分支點。

也可能需要針對-mm、linux-next或子系統樹生成版本，以便於更廣泛的測試和審查。
根據補丁的區域以及其他地方的情況，針對其他樹建立的補丁可能需要大量的工作來
解決衝突和處理API更改。

只有最簡單的更改才應格式化爲單個補丁；其他所有更改都應作爲一系列邏輯更改進行。
分割補丁是一門藝術；一些開發人員花了很長時間來弄清楚如何按照社區期望的方式來
分割。不過，這些經驗法則也許有幫助：

 - 您發布的補丁系列幾乎肯定不會是開發過程中版本控制系統中的一系列更改。相反，
   需要對您所做更改的最終形式加以考慮，然後以有意義的方式進行拆分。開發人員對
   離散的、自包含的更改感興趣，而不是您創造這些更改的原始路徑。

 - 每個邏輯上獨立的變更都應該格式化爲單獨的補丁。這些更改可以是小的（如「向
   此結構體添加欄位」）或大的（如添加一個重要的新驅動程序），但它們在概念上
   應該是小的，並且可以在一行內簡述。每個補丁都應該做一個特定的、可以單獨
   檢查並驗證它所做的事情的更改。

 - 換種方式重申上述準則，也就是說：不要在同一補丁中混合不同類型的更改。如果
   一個補丁修復了一個關鍵的安全漏洞，又重新排列了一些結構，還重新格式化了代
   碼，那麼它很有可能會被忽略，從而導致重要的修復丟失。

 - 每個補丁都應該能創建一個可以正確地構建和運行的內核；如果補丁系列在中間被
   斷開，那麼結果仍應是一個正常工作的內核。部分應用一系列補丁是使用
   「git bisct」工具查找回歸的一個常見場景；如果結果是一個損壞的內核，那麼將使
   那些從事追蹤問題的高尚工作的開發人員和用戶的生活更加艱難。

 - 不要過分分割。一位開發人員曾經將一組針對單個文件的編輯分成500個單獨的補丁
   發布，這並沒有使他成爲內核郵件列表中最受歡迎的人。一個補丁可以相當大，
   只要它仍然包含一個單一的 *邏輯* 變更。

 - 用一系列補丁添加一個全新的基礎設施，但是該設施在系列中的最後一個補丁啓用
   整個變更之前不能使用，這看起來很誘人。如果可能的話，應該避免這種誘惑；
   如果這個系列增加了回歸，那麼二分法將指出最後一個補丁是導致問題的補丁，
   即使真正的bug在其他地方。只要有可能，添加新代碼的補丁程序應該立即激活該
   代碼。

創建完美補丁系列的工作可能是一個令人沮喪的過程，在完成「真正的工作」之後需要
花費大量的時間和思考。但是如果做得好，花費的時間就是值得的。

補丁格式和更改日誌
------------------

所以現在你有了一系列完美的補丁可以發布，但是這項工作還沒有完成。每個補丁都
需要被格式化成一條消息，以快速而清晰地將其目的傳達到世界其他地方。爲此，
每個補丁將由以下部分組成：

 - 可選的「From」行，表明補丁作者。只有當你通過電子郵件發送別人的補丁時，這一行
   才是必須的，但是爲防止疑問加上它也不會有什麼壞處。

 - 一行描述，說明補丁的作用。對於在沒有其他上下文的情況下看到該消息的讀者來說，
   該消息應足以確定修補程序的範圍；此行將顯示在「short form（簡短格式）」變更
   日誌中。此消息通常需要先加上子系統名稱前綴，然後是補丁的目的。例如：

   ::

        gpio: fix build on CONFIG_GPIO_SYSFS=n

 - 一行空白，後接補丁內容的詳細描述。此描述可以是任意需要的長度；它應該說明補丁
   的作用以及爲什麼它應該應用於內核。

 - 一個或多個標記行，至少有一個由補丁作者的 Signed-off-by 簽名。標記將在下面
   詳細描述。

上面的項目一起構成補丁的變更日誌。寫一則好的變更日誌是一門至關重要但常常被
忽視的藝術；值得花一點時間來討論這個問題。當你編寫變更日誌時，你應該記住有
很多不同的人會讀你的話。其中包括子系統維護人員和審查人員，他們需要決定是否
應該合併補丁，分銷商和其他維護人員試圖決定是否應該將補丁反向移植到其他內核，
缺陷搜尋人員想知道補丁是否導致他們正在追查的問題，以及想知道內核如何變化的
用戶等等。一個好的變更日誌以最直接和最簡潔的方式向所有這些人傳達所需的信息。

在結尾，總結行應該描述變更的影響和動機，以及在一行約束條件下可能發生的變化。
然後，詳細的描述可以詳述這些主題，並提供任何需要的附加信息。如果補丁修復了
一個缺陷，請引用引入該缺陷的提交（如果可能，請在引用提交時同時提供其 id 和
標題）。如果某個問題與特定的日誌或編譯器輸出相關聯，請包含該輸出以幫助其他
人搜索同一問題的解決方案。如果更改是爲了支持以後補丁中的其他更改，那麼應當
說明。如果更改了內部API，請詳細說明這些更改以及其他開發人員應該如何響應。
一般來說，你越把自己放在每個閱讀你變更日誌的人的位置上，變更日誌（和內核
作爲一個整體）就越好。

不消說，變更日誌是將變更提交到版本控制系統時使用的文本。接下來將是：

 - 補丁本身，採用統一的（「-u」）補丁格式。使用「-p」選項來diff將使函數名與
   更改相關聯，從而使結果補丁更容易被其他人讀取。

您應該避免在補丁中包括與更改不相關文件（例如，構建過程生成的文件或編輯器
備份文件）。文檔目錄中的「dontdiff」文件在這方面有幫助；使用「-X」選項將
其傳遞給diff。

上面提到的標籤（tag）用於描述各種開發人員如何與這個補丁的開發相關聯。
:ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
文檔中對它們進行了詳細描述；下面是一個簡短的總結。每一行的格式如下：

::

	tag: Full Name <email address>  optional-other-stuff

常用的標籤有：

 - Signed-off-by: 這是一個開發人員的證明，證明他或她有權提交補丁以包含到內核
   中。這表明同意開發者來源認證協議，其全文見
   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`
   如果沒有合適的簽字，則不能合併到主線中。

 - Co-developed-by: 聲明補丁是由多個開發人員共同創建的；當幾個人在一個補丁上
   工作時，它用於給出共同作者（除了 From: 所給出的作者之外）。由於
   Co-developed-by: 表示作者身份，所以每個共同開發人，必須緊跟在相關合作作者
   的Signed-off-by之後。具體內容和示例見以下文件
   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`

 - Acked-by: 表示另一個開發人員（通常是相關代碼的維護人員）同意補丁適合包含
   在內核中。

 - Tested-by: 聲明某人已經測試了補丁並確認它可以工作。

 - Reviewed-by: 表示某開發人員已經審查了補丁的正確性；有關詳細信息，請參閱
   :ref:`Documentation/translations/zh_TW/process/submitting-patches.rst <tw_submittingpatches>`

 - Reported-by: 指定報告此補丁修復的問題的用戶；此標記用於表示感謝。

 - Cc：指定某人收到了補丁的副本，並有機會對此發表評論。

在補丁中添加標籤時要小心：只有Cc:才適合在沒有指定人員明確許可的情況下添加。

發送補丁
--------

在寄出補丁之前，您還需要注意以下幾點：

 - 您確定您的郵件發送程序不會損壞補丁嗎？被郵件客戶端更改空白或修飾了行的補丁
   無法被另一端接受，並且通常不會進行任何詳細檢查。如果有任何疑問，先把補丁寄
   給你自己，讓你自己確定它是完好無損的。

   :ref:`Documentation/translations/zh_TW/process/email-clients.rst <tw_email_clients>`
   提供了一些有用的提示，可以讓特定的郵件客戶端正常發送補丁。

 - 你確定你的補丁沒有荒唐的錯誤嗎？您應該始終通過scripts/checkpatch.pl檢查
   補丁程序，並解決它提出的問題。請記住，checkpatch.pl，雖然體現了對內核補丁
   應該是什麼樣的大量思考，但它並不比您聰明。如果修復checkpatch.pl給的問題會
   使代碼變得更糟，請不要這樣做。

補丁應始終以純文本形式發送。請不要將它們作爲附件發送；這使得審閱者在答覆中更難
引用補丁的部分。相反，只需將補丁直接放到您的消息中。

寄出補丁時，重要的是將副本發送給任何可能感興趣的人。與其他一些項目不同，內核
鼓勵人們甚至錯誤地發送過多的副本；不要假定相關人員會看到您在郵件列表中的發布。
尤其是，副本應發送至：

 - 受影響子系統的維護人員。如前所述，維護人員文件是查找這些人員的首選地方。

 - 其他在同一領域工作的開發人員，尤其是那些現在可能在那裡工作的開發人員。使用
   git查看還有誰修改了您正在處理的文件，這很有幫助。

 - 如果您對某錯誤報告或功能請求做出響應，也可以抄送原始發送人。

 - 將副本發送到相關郵件列表，或者若無相關列表，則發送到linux-kernel列表。

 - 如果您正在修復一個缺陷，請考慮該修復是否應進入下一個穩定更新。如果是這樣，
   補丁副本也應發到stable@vger.kernel.org 。另外，在補丁本身的標籤中添加一個
   「Cc: stable@vger.kernel.org」；這將使穩定版團隊在修復進入主線時收到通知。

當爲一個補丁選擇接收者時，最好清楚你認爲誰最終會接受這個補丁並將其合併。雖然
可以將補丁直接發給Linus Torvalds並讓他合併，但通常情況下不會這樣做。Linus很
忙，並且有子系統維護人員負責監視內核的特定部分。通常您會希望維護人員合併您的
補丁。如果沒有明顯的維護人員，Andrew Morton通常是最後的補丁接收者。

補丁需要好的主題行。補丁主題行的規範格式如下：

::

	[PATCH nn/mm] subsys: one-line description of the patch

其中「nn」是補丁的序號，「mm」是系列中補丁的總數，「subsys」是受影響子系統的
名稱。當然，一個單獨的補丁可以省略nn/mm。

如果您有一系列重要的補丁，那麼通常發送一個簡介作爲第〇部分。不過，這個約定
並沒有得到普遍遵循；如果您使用它，請記住簡介中的信息不會進入內核變更日誌。
因此，請確保補丁本身具有完整的變更日誌信息。

一般來說，多部分補丁的第二部分和後續部分應作爲對第一部分的回覆發送，以便它們
在接收端都連接在一起。像git和coilt這樣的工具有命令，可以通過適當的線程發送
一組補丁。但是，如果您有一長串補丁，並正使用git，請不要使用–-chain-reply-to
選項，以避免創建過深的嵌套。

