Gitmoji x Conventional Commit 工作流 (三) - 使用 commit-and-tag-version 自動化生成 CHANGELOG.md
變更日誌的意義與重要性
變更日誌是什麼?
在軟體專案中,變更日誌(Change Log) 是一份用來記錄專案功能變更、問題修復、優化內容的重要「歷史日記」。這份日誌的對象通常是開發者、測試人員。它可以幫助專案參與者快速掌握專案歷史,甚至在需要版本回滾時節省大量時間。
變更日誌最主要的目的是為了讓大家能「看懂版本變化」。它有幾個很實用的好處:
- 讓專案更透明,無論是團隊成員還是用戶,都能快速知道每次更新改了些什麼。
- 提高團隊效率,讓團隊成員快速理解改動,避免重複查詢。
- 輔助問題追蹤與版本回滾
如何寫出好的變更日誌?
可能你會覺得,寫個變更日誌能有多難?隨便列幾個點就好啦。但真要讓日誌清晰又有條理,還真有不少學問。這裡就不得不提到 Keep a Changelog。它是一套專門為變更日誌設計的標準,目的是幫助大家寫出「清晰且結構化」的日誌。這套標準幫我們解決了寫日誌的常見問題,比如內容亂、不知道該記哪些東西、不統一的格式等等。
好的變更日誌的核心原則
這套標準有幾個核心原則,非常值得參考:
- 為人而非機器書寫: 不用寫得像機器碼一樣複雜,越自然越好,重點是大家能看懂。
- 保持結構化與易讀性: 使用 Markdown 格式,方便快速跳轉或引用特定內容。
- 頂部留一個
Unreleased
區域: 未正式發布的改動都放在這裡,等發布時再歸檔到對應版本。 - 最新版本置頂: 日誌按照時間倒序排列,最新的放最上面,方便查找。
- 統一的日期格式: 建議使用
YYYY-MM-DD
,像 2024-11-21,這種格式清晰易懂,國際化也沒問題。 - 遵守語義化版本控制: 和版本號一樣,要讓讀者知道變更的範圍,比如新增功能是小版本更新,Bug 修復則是補丁版本。
- 分類記錄變更: 把每次改動歸類到以下幾種標籤裡,方便閱讀
- Added:新增的功能。
- Changed:改變的功能。
- Deprecated:不建議用的功能(但還沒刪)。
- Removed:刪掉的功能。
- Fixed:修復的 Bug。
- Security:修正的安全漏洞。
好的 Change Log 長什麼樣子?
來看看下面這個範例,這是一個符合 Keep a Changelog 標準的變更日誌:
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- v1.1 Brazilian Portuguese translation.
- v1.1 German Translation
### Changed
- Use frontmatter title & description in each language version template
- Replace broken OpenGraph image with an appropriately-sized Keep a Changelog
image that will render properly (although in English for all languages)
- Fix OpenGraph title & description for all languages so the title and
description when links are shared are language-appropriate
### Removed
- Trademark sign previously shown after the project description in version
0.3.0
## [1.1.1] - 2023-03-05
### Added
- Arabic translation (#444).
- v1.1 French translation.
### Fixed
- Improve French translation (#377).
- Fix missing logo in 1.1 pages.
### Changed
- Upgrade dependencies: Ruby 3.2.1, Middleman, etc.
### Removed
- Unused normalize.css file.
- Identical links assigned in each translation file.
範本的結構說明
Unreleased
區域: 還沒發布的改動先放這裡,等確定版本號時再移到下一節。- 版本章節: 每個版本對應一個章節,標明版本號和發布日期(例如
[1.0.0] - 2024-11-21
)。 - 分類標籤: 把變更內容分成
Added
(新增功能)、Fixed
(修復問題)等類別,方便快速檢索。
工具概覽: commit-and-tag-version
自動化 Change Log 工具選擇
雖說寫變更日誌很重要,但想想,如果你是一個專案的維護者,每更新一次版號就要回去翻上個版號到這個版號之間所有的 commit 紀錄,還要想辦法去蕪存菁,過濾掉一些不是很重要的變更紀錄,是一件多折騰人的事。
因此你會發現,很多開源專案都會使用自動化生成變更日誌的工具,來輔助專案維護者快速撈出重要的 commit 歷史紀錄,有些甚至會結合 CICD ,在分支合併進主幹時自動進版、發布 Release notes。我在尋找這類自動生成 Change Log 的工具時,發現市面上有不少選擇:
-
特點:
conventional-changelog
是一個專門用於生成 Change Log 的工具,它專注於解析 Git 提交訊息,根據 Conventional Commits 規範生成日誌。然而,它僅僅專注於 Change Log 的生成,沒有其他額外功能。 -
限制:
原生不支援 Gitmoji 格式,經 過我的實測,即使跟著網路上的教學搭配conventional-changelog-gitmoji-config
,仍無法正確生成 Change Log。
-
特點:
standard-version
是一個多功能工具,除了生成 Change Log,還包含自動版本升級(bumping)、生成 Git Tag 和提交(commit)的功能。 -
現狀:
它是commit-and-tag-version
的前身,但目前已經被社群標記為 deprecated(停止維護)。主要原因是維護停滯、功能擴展困難,無法滿足更多使用場景需求。
-
特點:
commit-and-tag-version
是standard-version
的 Fork,並進一步改進和擴展功能:- 持續維護: 提供社群支持,保持與最新需求的同步。
- 靈活配置: 更細緻的參數控制,滿足多場景應用。
- 高整合性: 繼承了
standard-version
的全部功能,並支持.versionrc
文件進行自定義。
-
特點:
semantic-release
是功能最強大的選項,除了 Change Log 的生成,還可以結合複雜的自動化工作流(如自動推送、發佈到 npm 或 GitHub)。 -
限制:
設定相對複雜,對於單純關注 Change Log 生成的 專案來說,可能顯得過於繁重。本篇文章的範疇並不涉及與遠端倉庫的整合,因此不選擇這個工具。
我將上述工具都下載下來實際測試後,最終選擇了
commit-and-tag-version
。相比其他工具,commit-and-tag-version
可能是目前功能性相對完整且配置靈活的選擇,且最重要的是,它目前仍然持續在更新,短期內不用擔心沒有人維護。
commit-and-tag-version 的基本工作流
根據官方文件,commit-and-tag-version
的執行流程如下:
-
遵循 Conventional Commits 規範:
確保專案的提交訊息格式符合 Conventional Commits 標準。
-
執行
commit-and-tag-version
指令:- 檢索當前版本號: 從
packageFiles
或最新的 Git Tag 中獲取版本號。 - 版本升級: 根據提交訊息自動升級版本號(bump)。
- 生成 Change Log: 使用
conventional-changelog
底層工具生成結構化的日誌。 - 生成 Commit: 自動提交包含新版本號和 Change Log 的變更。
- 生成 Git Tag: 添加新的版本 Tag。
- 檢索當前版本號: 從
commit-and-tag-version
提供了一個非常實用的功能焦作 Dry Run Mode
。可以預覽即將執行的命令與生成的 Change Log,避免直接修改檔案或 Git 紀錄。
-
使用方式:
npx commit-and-tag-version --dry-run
-
輸出示例:
$ commit-and-tag-version
✔ bump version from 1.0.0 to 1.1.0
✔ generate CHANGELOG.md
[Dry Run Mode] Skipping tag creation and commit.
聚焦 Change Log 生成
不過在本篇文章中,我們僅關注 Change Log 的自動生成,因此需要在CLI 參數或是設定檔中禁用其他功能,如版本升級、提交與 Tagging。commit-and-tag-version
支援透過 .versionrc
、.versionrc.json
或 .versionrc.js
文件進行配置。所有 CLI 中的參數均可直接寫入設定檔。
以下是 .versionrc
配置範例,跳過一些預設的流程:
{
"skip": {
"bump": true, // 禁用版本升級
"changelog": false,
"commit": true, // 禁用自動提交
"tag": true // 禁用自動 Tag
}
}
補充:也可以在 CLI 中加上
—skip.bump
/—skip.commit
/—skip.tag
} 等參數的方式來跳過預設流程
commit-and-tag-version
預設使用 conventionalcommits preset 這套規則,找出特定類型的 commit 紀錄,以特定的格式填寫進變更日誌。當然,我們也可以在 .versionrc
中調整變更日誌的格式。所有與 Change Log 相關的設定規範定義於 Conventional Changelog Configuration Spec (v2.1.0)。