Conventional Commits 的實踐指南:寫出乾淨的提交訊息
Conventional Commits 的實踐指南:寫出乾淨的提交訊息
前言:
你是不是也常遇到這樣的情況:翻開 Git 的 Commit 記錄,滿滿的「Update」、「Fix bug」或乾脆直接用 emoji 混過去。在團隊協作中,這種隨意的 Commit Message 不但讓歷史紀錄難以理解,還可能拖累整個專案的自動化流程,甚至影響版本管理的準確性。
這就是 Conventional Commit 派上用場的時候了!它是一套簡單又實用的規範,幫助你把 Commit Message 寫得清楚又有條理。不僅讓版本歷史一目了然,還能輕鬆實現自動生成變更日誌,甚至和語意化版本控制(Semantic Versioning)無縫接軌。
接下來,這篇文章會一步步帶你了解什麼是 Conventional Commit、它的格式怎麼寫、為什麼它能對專案有幫助,以及在日常開發中要怎麼用它來讓你的工作更高效,讓團隊合作更順暢!
什麼是 Conventional Commit?
定義與目的
簡單來說,Conventional Commit 就是一套用來規範 Git Commit Message 的寫法規則。它的目的是幫助我們在版本控制中維持一致性與可讀性,同時為自動化工具提供足夠的資訊,讓整個開發流程更有效率。
那為什麼要這麼麻煩規範 Commit Message 呢?其實,Conventional Commit 的好處不只是看起來整齊,它還能幫助你做到以下幾件事:
提升版本控制的可讀性
清楚的 Commit Message 讓團隊中的每個人都能快速理解變更內容,甚至可以直接找到問題的根源。
支援自動生成變更日誌(Change Log)
根據規範好的 Message,工具可以自動整理出完整的變更日誌,節省手動編寫的時間。
輔助語意化版本控制(Semantic Versioning)
結合 Semantic Versioning,可以根據不同類型的 Commit 自動決定版本號的升級方式,讓版本管理更加可靠。
基本格式
Conventional Commit 的格式其實很簡單,看起來像這樣:
讓我們來分解一下每個部分的用途:
type(Commit 類型): 描述這次 Commit 的性質,例如是新增功能(feat)、修復問題(fix),還是進行雜項更新(chore)。
scope(影響範圍,可選): 用來標記這次變更影響的範圍,比如是哪個模組或功能。如果影響範圍明確,建議加上,能讓訊息更清楚。
description(簡短描述): 一句話清楚說明這次 Commit 的內容。最好簡短有力,保持在 50 字以內。
body(詳細說明,可選): 如果需要,可以在這裡詳細描述 Commit 的背景、動機或實現方式。
footer(註解或 Breaking Change,可選): 用來記錄像 Breaking Change 的訊息,或者相關 Issue 的 ID。例如:
BREAKING CHANGE: 改變了 API 的回傳結構Resolves #123
與 Semantic Versioning 的關係
Conventional Commit 和 Semantic Versioning(語意化版本控制) 是一對好搭檔。後者使用版本號的格式 MAJOR.MINOR.PATCH,分別代表:
MAJOR:重大改動(可能破壞向後相容性)
MINOR:新增功能(不影響向後相容性)
PATCH:修正錯誤(不影響向後相容性)
而 Conventional Commit 的規範則可以幫助我們自動決定版本號的升級規則:
使用 fix 的 Commit,通常只影響 PATCH 版本,表示修正錯誤。
使用 feat 的 Commit,會影響 MINOR 版本,表示新增功能。
如果有 BREAKING CHANGE,就會升級 MAJOR 版本,因為改動可能影響到向後相容性。
常用 Commit 類型與範例
常見的 Commit 類型
在使用 Conventional Commit 時,除了大家熟悉的 feat(新增功能)和 fix(修正 Bug),其實還有很多其他類型的 Commit 可以用來描述不同的變更。以下推薦一套我滿喜歡的類型定義集 @commitlint/config-conventional ,這套規範是基於 Angular 團隊的開發慣例 所制定的,目前在開源社群中被廣泛採用。
feat: 表示新增了一個新的功能。通常會影響 MINOR 版本號。
fix: 用來描述修復的問題。通常會影響 PATCH 版本號。
docs: 任何文檔的更新,例如 README 或 API 文件的修改。不會影響程式碼執行。
style: 只涉及程式碼的格式化,與程式邏輯無關的修改,比如縮排、逗號位置等。
refactor: 改善程式結構或優化,未新增功能,也沒有修正 Bug。
test: 專門針對測試檔案的修改。
chore: 一些雜項工作,例如工具設定、依賴更新等。
build: 涉及編譯過程的修改,例如修改 webpack、rollup 等配置。
ci: 與 CI/CD 腳本或流程有關的更動。
perf: 專注於提升執行效能的修改。
revert: 如果需要回退某次提交,使用 revert。
範例
以下是幾個實際的使用場景,幫助你更好理解這些類型的應用:
新增功能提交
feat(profile): add profile picture upload feature
Bug 修正提交
fix(payment): resolve issue with invalid card numbers
Breaking Change
feat(api): migrate to new authentication flowBREAKING CHANGE: user API now requires OAuth token
文件變更提交
docs(api): add endpoint usage examples
回退某次提交
revert: revert "feat(auth): add login with Google"
常見問題與注意事項
常見問題
Q:當提交符合多種提交類型時,該怎麼辦?
當一次提交同時符合多種類型,建議選擇最能代表此次變更的主要類型。例如,如果新增功能時也修正了 Bug,應選擇 feat,並在正文中補充說明修正的內容。
Q: 什麼時候該寫 Scope?
scope 是可選的,但建議在影響範圍清晰時加以描述,例如指定某個功能模組、檔案或子系統。這能幫助開發者快速理解變更的影響範圍,如果範圍不明確或無特定模組影響,可以省略。
Q: Commit Message 一定要用英文嗎?
Commit Message 的語言應以團隊習慣為準。英文是國際化的標準選擇,但如果團隊成員習慣用中文或其他語言,也可以使用母語,只要訊息內容清楚、一致即可。
Q: 如果不小心用錯提交類型,該怎麼辦?
可以使用 git commit --amend 修正最近一次提交訊息,或者使用 git rebase -i
Q: 如何處理回退提交 (revert commit)?
在實際開發中,回退提交(revert commit)有時是不可避免的,但這可能比想像中複雜得多。你需要考慮以下幾個問題:
是回退一個提交還是多個提交?
如果是多個提交,需特別小心可能產生的衝突,並確保每個被回退的改動都處理妥當。
回退的是功能還是修復?
如果回退的內容是某個功能,那麼回退後的變更應該算作 修正檔(PATCH) 嗎?這需要根據專案的語意化版本策略來決定。
Conventional Commit 並沒有對回退行為做出強制規範,這留給工具作者或團隊自行定義。一個推薦的方式是使用 revert 類型,並在頁腳中標註被回退的 Commit 的 SHA 雜湊。這樣能清楚表達回退的意圖,同時為工具處理提供必要的資訊。
範例:
revert: let us never again speak of the noodle incidentRefs: 676104e, a215868
注意事項
避免過長的描述
description 部分應保持簡潔,建議 50 個字以內即可清楚表達變更的重點。詳細的內容可以放在 body 區塊中,避免讓標題過於冗長。
合理的提交粒度
每次提交應專注於單一變更,保持適當的粒度。過大的提交會讓變更難以追溯,而過於零碎的提交則可能讓記錄過於冗長,增加維護成本。
大小寫規範
Commit Message 的 type 和 scope 建議使用小寫字母,以保持格式的一致性。唯有 BREAKING CHANGE 必須大寫,且後需接分號與空格。
BREAKING CHANGE 的規範
當變更中包含破壞性更新(例如影響向後相容性),必須在頁腳中明確標註 BREAKING CHANGE,並描述破壞性改動的原因及影響。例如:
BREAKING CHANGE: user authentication now requires OAuth tokens
頁腳格式的書寫規範
頁腳應另起一行,並清楚標明變更類型或符記,例如 BREAKING CHANGE 或關聯 Issue 編號。正確格式如下:
BREAKING CHANGE: removed deprecated endpoint /api/v1/usersCloses #123
提交訊息的格式需機械可讀
確保提交訊息的格式符合 Conventional Commit 的規範,讓工具可以自動解析並生成變更日誌、版本升級或其他自動化操作。
實用工具推薦
在實際開發中,想要高效地執行 Conventional Commit 規範,幾款強大的工具可以大幅簡化你的工作,讓規範的執行更輕鬆且準確。
Commitizen
功能:
Commitizen 是一款專門用來輔助生成規範化 Commit Message 的工具。它可以引導你一步步填寫符合規範的訊息,避免手寫格式時出錯。
特點:
透過互動式 CLI 進行提交,讓規範化流程更直覺。
支援多種規範模板,例如 Conventional Commit。
Commitlint
功能:
Commitlint 是一款校驗工具,用來檢查你的 Commit Message 是否符合規範,避免提交不合規的訊息。
特點:
可整合到 CI/CD 流程中,自動化檢查提交訊息。
支援高度自訂,可以針對團隊需求調整規則。
Standard Version
功能:
Standard Version 是一款自動化工具,基於 Conventional Commit 規範,幫助你自動生成語意化版本號和變更日誌(Change Log)。
特點:
根據提交訊息,計算版本升級類型(MAJOR、MINOR 或 PATCH)。
自動更新版本號、生成變更日誌,甚至可以幫你打 Tag。
無需手動操作,讓發版流程更高效。
Husky
功能:
Husky 是一款用來管理 Git Hook 的工具,能幫助你在特定 Git 操作(如提交、推送)時執行自動化流程,例如校驗提交訊息。
特點:
配合 Commitlint 使用,實現提交訊息的本地校驗。
可用於其他操作,如執行測試、格式化程式碼等,擴展性強。
Reference
Conventional Commits