前言
在團隊開發中,我們通常會架設自己的 Git 伺服器,團隊成員根據權限進行程式碼的拉取(pull)與推送(push)。然而,當需要貢獻程式碼至一個沒有推送權限的專案,或是在嚴格的存取控制下進行協作時,直接推送便不可行。
這就是 Git Patch 工作流程發揮作用的地方。它允許我們將一個或多個提交(commit)打包成獨立、可傳遞的 .patch 檔案。接收者可以將這些檔案應用到他們的程式碼庫中,並完整保留原始的提交資訊,如作者、日期與訊息。
Git Patch 基礎機制
Git 提供了兩種主要的 Patch 生成與應用方式:git diff
/git apply
與 git format-patch
/git am
。它們看似相似,但在功能和應用場景有著本質的區別。
何時使用哪種方式(快速判斷)
- 若只想分享檔案內容差異、且不需要保留原作者與提交歷史:用
git diff
+git apply
。 - 若要保留原作者、提交訊息與可直接匯入 commit 歷史:用
git format-patch
+git am
(推薦於正式貢獻流程)。
工作流程 1:git diff
/ git apply
(僅應用程式碼變更)
這種方法僅關心檔案內容的差異,生成的 .patch 檔不包含任何提交的元數據,如作者、日期或提交訊息。
|
|
工作流程 2:git format-patch
/ git am
(保留作者資訊)
這是更推薦的標準做法。format-patch
生成的 .patch
檔實質上是一個郵件格式的檔案,完整保留了原始提交的所有元數據。維護者使用 git am(apply from mailbox)應用它時,能夠完美還原原始的提交歷史。
|
|
DCO(Developer Certificate of Origin)
DCO 是由 Linux Foundation 制定的來源聲明;加入
Signed-off-by
表示你聲明此貢獻由你(全部或部分)創作,且有權依該授權提交。常見用法:在套用 patch 或 commit 時加入簽署以保留來源與責任。
範例:
git am --signoff 000*.patch
git commit -s -m "Your commit message"
簽署後會在 commit 中加入
Signed-off-by: Name <you@example.com>
。
Yocto / BitBake 實務應用
在嵌入式 Linux 開發中,Yocto Project 是構建客製化系統的標準。BitBake 負責建置與組裝大量開源套件;CVE 修補通常以 .patch
形式加入 recipe(以 SRC_URI
引用),並由 BitBake 在 do_patch
階段自動套用。
使用 ‘.patch’ 修正 CVE 錯誤,其原因是盡可能追求系統的穩定性,產品的 Linux 核心通常依賴特定套件的特定版本,避免因升級帶來非預期的風險。然而,這也意味著我們無法透過簡單的版本升級來獲取安全性更新。此時,精準的漏洞修補便成為關鍵。
這正是商業級軟體組成分析(software composition analysis,SCA)工具發揮價值的地方,例如 Vigiles 或 Black Duck。這些工具能深入掃描專案的原始碼,分析出所有使用的開源元件,並比對出其中存在的已知漏洞。
一旦 SCA 工具報告了特定的 CVE 編號,開發者的任務就是根據這些編號,去上游專案或開源社群中尋找已經被製作好的修補程式。接著,將這些找到的 .patch
檔整合進 Yocto 的 BitBake Recipe 中,實現「不動主體、只修漏洞」的精準維護。
在 Recipe 中應用 Patch
Yocto 的 Recipe (.bb 檔) 透過 SRC_URI
變數來管理原始碼和修補程式。開發者只需將 format-patch 生成的 .patch 檔放置於指定目錄,並在 SRC_URI
中引用即可。
假設我們要為 example-package 套件修補兩個 CVE,其 Recipe 可能如下所示:
|
|
在 Yocto 的建置過程中 (do_patch
任務),BitBake 會自動解壓縮原始碼,並依序應用 SRC_URI
中定義的所有 patch。
建議以 CVE 編號命名 patch,例如:CVE-2021-3566.patch
。這能讓自動化工具(如 Yocto 的 cve-check
)根據檔名標記為 Patched。但該 patch 是否真正解決漏洞。這部分沒辦法實際得知。
結論
掌握 Git 的 patch 工作流程,能讓協作與維護更有條理且容易驗證。簡單來說:當只需套用檔案差異、且不保留原始提交資訊時,git diff
/git apply
是快速的選擇;當需要保留作者、訊息與可回溯的提交歷史時,則應優先使用 git format-patch
/git am
。
在 Yocto 與嵌入式產品維護情境中,採用以 CVE 編號命名的 patch(例如 CVE-2021-3566.patch
)並透過 recipe 的 SRC_URI
引入,可讓 BitBake 在 do_patch
階段自動套用,並與 SCA 工具與 cve-check
等自動化稽核流程整合。但請記得:檔名標註僅表示已嘗試修補,仍需透過建置、測試與回歸驗證來確認漏洞真被修復。
製作 patch 時務必注意提交標題中的特殊字元與編碼問題。若在標題使用 gitmoji
、emoji(或 emoji shortcode,如 :sparkles:
),標題內的冒號或其他特殊字元可能會因字元編碼、字型呈現或不同 Git 版本的處理差異,而導致在套用 patch 時發生錯誤。建議提交標題以英文為優先;若需使用本地語言,應避免使用特殊符號或控制字元,並確認 patch 檔案採用 UTF-8 編碼且與使用的 Git 版本相容,最後以建置與測試驗證 patch 是否能正確套用並完成修復。
最後,我個人開發時更常用 git diff --cached | code -
來快速檢視 staged 內容;如果想把提交訊息寫得更好,可參考《利用 GPT 工具輕鬆撰寫高品質的 Git 提交內容》。