這是我第一次發 patch 的全紀錄,並且由 [visitorckw](https://github.com/visitorckw),以下簡稱小邱,在我犯錯時糾正我,大力感謝! 這 patch 的目標是在 Linux Kernel 裡修改錯字,並且是修 Document 裡的錯字,因為比較無傷大雅,推薦大家也這樣做! 另外我寫了貢獻時使用 [Kbuild](https://hackmd.io/@eleanorLin/Kbuild) 的步驟,改到 code,要做編譯測試可以看看此文章。 ## 發 patch 主要流程 1. 用 [codespell](https://github.com/codespell-project/codespell) 找錯字 2. 用 [git add](https://git-scm.com/docs/git-commit), [git commit](https://git-scm.com/docs/git-commit) 3. 生成 patch 4. 找要寄給哪些人 5. 用 [git send-email](https://git-scm.com/docs/git-send-email/2.45.0) 寄信 向 Linux Kernel 發 patch 的唯一路徑是透過 email,不要到 Linux Kernel 的 github 的 PR 處做修改。 務必閱讀 官方文件 [Submitting patches: the essential guide to getting your code into the kernel](https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html) ,另外我參考了他人文章 [提交第一份 Patch 到 Linux Kernel](https://hackmd.io/@steven1lung/submitting-patches?fbclid=IwY2xjawFHNo1leHRuA2FlbQIxMAABHXuARAidhoc3MR951zJezFSNOO_QEJaqgsmg1iRqWc1UbVee2d66QUZTYQ_aem_KHYbDpSeWfP7vU22fy0Irw), [第一次給Linux Kernel發patch](https://hackmd.io/@rhythm/BkjJeugOv) 結合出我的筆記 ## 開始貢獻! ### 前置作業 設定 git config、clone 下 kernel 原始碼、設定 smtp 的資料。 #### 設定 git config ``` $ git config --global user.email "your email" $ git config --name user.name "your name" ``` 此設定是為了讓 Git 知道你的身份。在提交 patch 時,會附上你的 Signed-off-by 標籤,用來確認這是你自願提供的 patch #### 取得原始碼 從官方的 Git 儲存庫中 clone Linux 核心源碼: ``` $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git ``` 之後建一個新的 branch ``` $ cd linux $ git checkout -b your_banch_ame ``` #### SMTP 設定 SMTP 設定,你可以透過配置 .gitconfig 來實現,這樣 Git 就能直接發送郵件 (我是使用 Gmail,因此以下配置 Gmail SMTP為例) ``` $ vi ~/.gitconfig ``` 然後在最後加上以下設定: ``` [sendemail] smtpencryption=tls smtpserver=smtp.gmail.com smtpuser=your@xxxx.com smtpserverport=587 smtpPass=你的APP密碼 ``` 參數介紹 - `smtpEncryption = tls`:設定電子郵件傳輸時使用 TLS 加密。 - `smtpServer = smtp.gmail.com`:指定 SMTP 伺服器的地址。這裡使用的是 Gmail 的 SMTP 伺服器。 - `smtpUser = youremail@gmail.com`:指定發送郵件的使用者帳號(即你的 Gmail 帳號)。 - `smtpServerPort = 587`:設定 SMTP 伺服器的 port ,587 是 Gmail 用來接受 TLS 加密連接的 port。 - `smtpPass = 你的APP密碼`:由於 Gmail 不允許直接使用密碼發送郵件,你需要生成一個應用程式專用密碼來替代,這是必須的。 #### 設定 app 密碼 進入 Google 帳戶,再點入安全性 1. 做兩步驟驗證 2. 設定應用程式密碼,打應用名稱,它就會產一組 16字字串,再貼上上述的 .gitconfig設定裡 (倘若跟我一樣找不到 "應用程式密碼",就直接在網頁上方的搜尋欄,搜尋 "應用程式密碼") 設定好,就開始我們的創造 patch 的過程! ### 1. 改錯字 首先安裝 codespell ``` $ pip install codespell ``` 接著在你在根目錄或是你想找錯字的目錄下的 terminal 打 ``` $ codespell ``` 就可以找到很多的錯字,但注意不要改到縮寫,Linux Kernel 有很多看起來奇怪的縮寫。改完、確定過後就可以儲存。 ### 2. 將修改加到本地倉儲裡 將修改存到暫存區(stage area) `$ git add .` 將此修改從暫存區移到本地倉儲裡 (repository)。以下命令會展開編輯器能夠打 commit message (預設 nano,我是有再去設成 vim 打開) `$ git commit -s -v` 參數解釋 - `-s` 是 --signoff 會自動加 `Signed-off-by` tag - `-v` 是 --verbose 底部顯示 HEAD 提交和將要提交的內容之間的差異 **寫 commit message的注意事項:** - 標題不用加 `[PATCH]` ,後來生成 patch 時它會自動補。 - commit message內容 要在 commit 時就要寫好,不要在 patch 裡改 commit message。 標準的長相: ``` 子系統: 總結修改 較詳細的說明修改 Signed-off-by: 名字 <email> ``` 內文要說明 1. 為什麼 kernel 需要這 patch,說服維護者。 2. 解釋 patch 的整體設計、實作細節與考量。 3. 如果是優化效能的 patch ,要含測試結果 但我這只是修錯字,不需要寫這麼多。 注意: 1. 每 75 字要換行 2. 標題與內文要保持精簡,如 [The perfect patch](https://www.ozlabs.org/~akpm/stuff/tpp.txt?fbclid=IwY2xjawFHPqNleHRuA2FlbQIxMAABHXr2wzF6ELKNC4MhQOjJGCMfJRLXmNG420k506x4jqgdhunsSWRLkb3lFQ_aem_kY8oEey-34P-eOd3CX_nJQ) 舉的例子 ,內文不要以 "This patch does ..." 開頭,太廢話了。 我第一次的 commit message,如下圖:  後來被維護者提醒,我修改的子系統有自己的 subject prefix 規定,因此寫 commit 的標題時,也要去查查子系統是否有特別規定。 如我修改的 devicetree/binds的規定: [Submitting Devicetree (DT) binding patches](https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters) 倘若寫完 commit messaage 後,還要再修改這一個 commit,使用 `$ git commit --amend` 做修改 :::info 小邱補充: 若是要準備發送 patch series (多個 commit) 並且要更動中間的 patch/commit 可能需要使用 git rebase -i ::: ### 3. 生成 patch 用 [`git format-patch`](https://git-scm.com/docs/git-format-patch) 創建 patch `$ git format-patch master`: 會與 master 做比較,之後生成 patch 生成成功,會出現 patch 的檔名  (如果有多個 patches,要當 patches series 送 upstream,記得加 cover letter,命令為: `git format-patch --cover-letter master`,並且再編輯 cover letter) 接著手動檢查 patch 的風格 > - 一個 `from` 行指出 patch 作者。後跟空行(僅當發送 patch 的人不是作者時才需要)。 > - commit message > - 一個空行 ! > - `Signed-off-by:`。 > - `---` 的標記線。 > - 任何其他不適合放在變更 log 的註釋。 > - `diff` 。 除了手動,還可以用腳本檢查 patch 是否存在風格的錯誤 `$ ./scripts/checkpatch.pl --strict patch檔名` 舉例:  #### 倘若 patch 沒有第一次就過 那麼就先去把錯誤修一修後,將步驟1 2走過一遍,並且要**將多個 commit 做 squash**。 ##### squash 作法: 1. 先確定要squash 幾個 commit ``` $ git log --oneline ``` 2. 進入互動模式的 rebase 假設我要 squash 的 commit 數為 3 ``` $ git rebase -i HEAD~3 ``` 這命令會打開編輯器,並顯示最近三個的提交 ``` pick abc1234 Commit message 1 pick def5678 Commit message 2 pick ghi9012 Commit message 3 ``` 除第一個提交以外的pick改為squash ``` pick abc1234 Commit message 1 squash def5678 Commit message 2 squash ghi9012 Commit message 3 ``` 最後儲存退出編輯器。 書寫 commit message: 倘若在某維護者指出錯誤前,有人回信給你 reviewed-tag 或其他tag 時,在 commit message 裡,記得在你的 Signed-off tag 之前,按收到 tag 的順序加上。 之後生成 patch 指令如下,標題前綴 [PATCH v數字] (此舉例不是 patch series) ``` $ git format-patch master --subject-prefix='PATCH v2' ``` 或是 ``` $ git format-patch master -v 2 ``` :::info 小邱補充: 另外有些子系統 (像是 net) 需要在此處標註說這個 patch 是要 apply 到當前主線的修正還是 apply 到 next 為下個 merge window 做準備 ::: patch 中的`---` 以下是討論非 chagnelog 本身的資訊 此區可寫如下: 1. 敘述前版與這版的差異 2. 如果要別人給我的 tag 拿掉,也在此處說明原因,例如因為更動太多 之類等,所以要拿掉或是期待 re-confirming tag 等.. 3. 附上 前幾版 的 Link。 等內容。 以我第五版的 patch 的當範例  ### 4. 找出要寄 patch 給誰 兩種確定要寄給誰的方式 `./scripts/get_maintainer.pl [patch]` `./scripts/get_maintainer.pl -f [修改檔案的相對路徑]`  小邱說 commit_signer 是對此檔案或目錄比較多貢獻的人,這可以選擇不要寄,所以主要就是 maintainer, 子系統的 reviewer, support 與 open list 要寄,還有已經給 tag 的開發者! ### 5. 發信! 因為 patch 的要求是純文字,所以不建議使用 Gmail 等 email 服務,它們會自動轉換格式或附加其他內容,純文字的發送需要在 Gmail 額外設定。 因此發 patch 較方便的方式是使用 git send-email 發信。 git send-email 使用: `$ git send-email --to 寄件人 --cc 寄件人 patch` 簡單範例 `$ git send-email --to laurent.pinchart@ideasonboard.com --cc devicetree@vger.kernel.org,visitorckw@gmail.com 0001-docs-devicetree-Fix-typo-in-lvds.yaml.patch` 注意: git send-email 不論你有沒有寄件人寫到,tag 的維護者,只要有在 patch 裡提及維護者的 email,此 patch 也會寄給他! 所以要測試寄信給自己,要先去 commit message 把 tag 拿掉,真正發信時,再記得把 tag 補回去! #### 5. 成功發信 恭喜你發出信囉! 接著等收信。 倘若犯錯太誇張,並且剛好維護者偏沒耐心的話,那可能會收不到回信。發信後一周後再仔細看看哪步驟做錯吧。 ### 最後補充錯誤修正的過程與心得 1. 我 git config 的名字, email 與 github 不匹配。被小邱提醒,所以我去 github 改完又快速重跑以上流程。 2. 我在第一版發信的時候,我用腳本找到 13 個的維護者與 open list,在發送郵件前很猶豫只是改錯字有需要寄這麼多人嗎? 我最終只寄了兩個維護者,其餘 11 個就都 Cc。我覺得不放心,跑去詢問 [jserv](https://wiki.csie.ncku.edu.tw/User/jserv) 老師。他說: "只是改錯字,不用 Cc 太多人,先觀察這些開發者的活躍程度",所以初次發送 patch 的各位可以借鏡。另外,我後來也被維護者說我只是改錯字,花太多位開發者的時間了。 3. 第二版寄件時 commit message 有加上給我 tag 的維護者。接著在我多次寄測試信給自己時,他也一併收到了... 4. 我第三版是要多修一個錯字,發出第三版時,不知道要把所有的commit 合併成一個 commit。所以我就收到 k 先生的信,問說我怎麼把所有東西 drop掉了 ... 小邱解釋: - 要替維護者想,所以我也不該期待維護者要手動幫你做 squash - > 不同版本代表前一個版本會直接被拋棄 > 文件裡面明明就有寫說你不可以期待維護者都有看過或者自己會去看前面的版本,所以你的 patch 要直接包含完整的資訊。 ## 我的 patch 紀錄 v1 Link: https://lore.kernel.org/lkml/20240901133046.962263-1-eleanor15x@gmail.com/ v2 Link: https://lore.kernel.org/lkml/20240903164242.2188895-1-eleanor15x@gmail.com/ v3 Link: https://lore.kernel.org/lkml/20240904125812.2761993-1-eleanor15x@gmail.com/ v4 Link: https://lore.kernel.org/lkml/20240904160118.2773055-1-eleanor15x@gmail.com/ v5 Link: https://lore.kernel.org/lkml/20240905151943.2792056-1-eleanor15x@gmail.com/ 最終,Rob收了我的修改 (撒花慶祝!) Link: https://lore.kernel.org/lkml/172566015521.2278562.15089620078479163976.robh@kernel.org/ 由於發 patch 過程,犯錯犯太多,感覺我是在 lkml 上發垃圾信的人,希望大家能借鏡我的錯誤,順利發出 patch ! 最後的最後,感謝小邱指導!
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up