Git 每次提交代碼,都要寫 Commit message(提交說明),否則就不允許提交。
$ git commit -m "hello world"
上面代碼的-m
參數,就是用來指定 commit mesage
的。
如果一行不夠,可以只執行git commit
,就會跳出文本編輯器,讓你寫多行。
$ git commit
可以這樣
這樣
Funny initial git commit messages
或者這樣
一般來說,commit message
應該清晰明了,說明本次提交的目的。
目前,社區有多種
Commit message
的寫法規范。本文介紹Angular規范(見上圖),這是目前使用最廣的寫法,比較合理和系統化,并且有配套的工具。
Commit message 的作用
格式化的Commit message,有幾個好處。
(1)提供更多的歷史信息,方便快速瀏覽。比如,下面的命令顯示上次發布后的變動,每個commit占據一行。你只看行首,就知道某次 commit 的目的。
$ git log <last tag> HEAD --pretty=format:%s
(2)可以過濾某些commit(比如文檔改動),便于快速查找信息。
比如,下面的命令僅僅顯示本次發布新增加的功能。
$ git log <last release> HEAD --grep feat
3)可以直接從commit生成Change log。
Change Log 是發布新版本時,用來說明與上一個版本差異的文檔,詳見后文。
Commit message 的格式
每次提交,Commit message 都包括三個部分:Header,Body 和 Footer。
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
其中,Header
是必需的,Body
和 Footer
可以省略。
不管是哪一個部分,任何一行都不得超過72個字符(或100個字符)。這是為了避免自動換行影響美觀。
Header
Header部分只有一行,包括三個字段:type
(必需)、scope
(可選)和subject
(必需)。
type
type
用于說明commit
的類別,只允許使用下面7個標識。
feat
新功能(feature)fix
修補bugdocs
文檔(documentation)style
格式(不影響代碼運行的變動)ref
重構(即不是新增功能,也不是修改bug的代碼變動)test
增加測試chore
構建過程或輔助工具的變動
如果type
為feat
和fix
,則該commit
將肯定出現在Change log
之中。其他情況(docs
、chore
、style
、refactor
、test
)由你決定,要不要放入Change log
,建議是不要。
scope
scope
用于說明commit
影響的范圍,比如數據層、控制層、視圖層等等,視項目不同而不同。subject
subject
是commit
目的的簡短描述,不超過50個字符。
以動詞開頭,使用第一人稱現在時,比如
change
,而不是或changed
changes
第一個字母小寫
結尾不加句號(.)
Body
Body 部分是對本次 commit 的詳細描述,可以分成多行。下面是一個范例。
More detailed explanatory text, if necessary. Wrap it to
about 72 characters or so.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Use a hanging indent
有兩個注意點。
- 使用第一人稱現在時,比如使用
change
而不是或changed
changes
- 應該說明代碼變動的動機,以及與以前行為的對比
Footer
Footer 部分只用于兩種情況。
- 不兼容變動
如果當前代碼與上一個版本不兼容,則Footer
部分以BREAKING CHANGE
開頭,后面是對變動的描述、以及變動理由和遷移方法。
BREAKING CHANGE: isolate scope bindings definition has changed.
To migrate the code follow the example below:
Before:
scope: {
myAttr: 'attribute',
}
After:
scope: {
myAttr: '@',
}
The removed `inject` wasn't generaly useful for directives so there should be no code using it.
- 關閉 Issue
如果當前commit
針對某個issue
,那么可以在Footer
部分關閉這個issue
。
Closes #234
也可以一次關閉多個 issue 。
Closes #123, #245, #992
Revert
還有一種特殊情況,如果當前commit
用于撤銷以前的commit
,則必須以revert:
開頭,后面跟著被撤銷Commit
的Header
。
revert: feat(pencil): add 'graphiteWidth' option
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
Body
部分的格式是固定的,必須寫成This reverts commit <hash>
,其中的hash
是被撤銷commit
的SHA
標識符。
如果當前commit
與被撤銷的commit
,在同一個發布(release
)里面,那么它們都不會出現在Change log
里面。如果兩者在不同的發布,那么當前commit
,會出現在 Change log
的Reverts
小標題下面。
Commitizen
Commitizen是一個撰寫合格Commit message
的工具。
安裝命令如下。(遇到缺少package.json文件的解決辦法在文章最后)
$ npm install -g commitizen
$ npm install -g cz-conventional-changelog
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
以后,凡是用到git commit
命令,一律改為使用git cz
。這時,就會出現選項,用來生成符合格式的Commit message
。
validate-commit-msg
validate-commit-msg 用于檢查 Node 項目的 Commit message 是否符合格式。
它的安裝是手動的。
首先,拷貝下面這個JS文件,放入你的代碼庫。文件名可以取為validate-commit-msg.js
。
接著,把這個腳本加入Git
的hook
。下面是在package.json
里面使用ghooks
,把這個腳本加為commit-msg
時運行。
"config": {
"ghooks": {
"commit-msg": "./validate-commit-msg.js"
}
}
然后,每次git commit
的時候,這個腳本就會自動檢查Commit message
是否合格。如果不合格,就會報錯。
$ git add -A
$ git commit -m "edit markdown"
INVALID COMMIT MSG: does not match "<type>(<scope>): <subject>" ! was: edit markdown
生成 Change log
如果你的所有Commit
都符合Angular
格式,那么發布新版本時,Change log
就可以用腳本自動生成(例1:karma/CHANGELOG.md, 例2:btford/grunt-conventional-changelog)。
生成的文檔包括以下三個部分。
- New features
- Bug fixes
- Breaking changes
每個部分都會羅列相關的commit
,并且有指向這些commit
的鏈接。當然,生成的文檔允許手動修改,所以發布前,你還可以添加其他內容。
conventional-changelog-cli就是生成Change log
的工具,運行下面的命令即可。
$ npm install -g conventional-changelog-cli
$ cd my-project
打印到屏幕
$ conventional-changelog -p angular -i CHANGELOG.md -w
輸出到文件
$ conventional-changelog -p angular -i CHANGELOG.md -s
上面命令不會覆蓋以前的Change log
,只會在CHANGELOG.md
的頭部加上自從上次發布以來的變動。
如果你想生成所有發布的Change log
,要改為運行下面的命令。
$ conventional-changelog -p angular -i CHANGELOG.md -s -r 0
為了方便使用,可以將其寫入package.json
的scripts
字段。
{
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0"
}
}
以后,直接運行下面的命令即可。
$ npm run changelog
缺少package.json文件
因為commitizen
工具是基于Node.js的,而我們iOS項目工程目錄下是沒有package.json
文件,所以會報錯:
Error: ENOENT: no such file or directory, open '/Users/***/package.json
關于這個問題,可以參考這個commitizen
的issue:Usage in non-node projects?,對于非Node的項目,我們可先在我們項目中添加一個空的package.json
文件,然后再輸入命令:
$ npm init --yes
先初始化配置package.json文件,然后再輸入命令:
$ commitizen init cz-conventional-changelog --save --save-exact
參考文章: