前言
git
作為一個(gè)開(kāi)發(fā)人員必不可少的工具,代碼提交也是日常一個(gè)非常頻繁的操作,如果你或你的團(tuán)隊(duì)目前對(duì)提交信息還沒(méi)有一個(gè)規(guī)范或約束,那么你有必要看看本文的內(nèi)容了。
為什么要規(guī)范提交信息
首先規(guī)范提交信息肯定是有必要的,簡(jiǎn)單總結(jié)下幾點(diǎn)好處:
- 讓項(xiàng)目的維護(hù)或使用人員能了解提交了哪些更改
- 清晰的歷史記錄,可能某天自己就需要查到呢
- 規(guī)范的提交記錄可用于自動(dòng)生成修改日志(CHANGELOG.MD)
- 基于提交類型,觸發(fā)構(gòu)建和部署流程
使用什么規(guī)范
Conventional Commits
(約定式提交規(guī)范),是目前使用最廣泛的提交信息規(guī)范,其主要受AngularJS規(guī)范 的啟發(fā),下面是一個(gè)規(guī)范信息的結(jié)構(gòu):
[optional scope]:
//空一行
[optional body]
//空一行
[optional footer(s)]
規(guī)范說(shuō)明
type
提交的類別,必須是以下類型中的一個(gè)
feat:增加一個(gè)新功能
fix:修復(fù)bug
docs:只修改了文檔
style:做了不影響代碼含義的修改,空格、格式化、缺少分號(hào)等等
refactor:代碼重構(gòu),既不是修復(fù)bug,也不是新功能的修改
perf:改進(jìn)性能的代碼
test:增加測(cè)試或更新已有的測(cè)試
chore:構(gòu)建或輔助工具或依賴庫(kù)的更新
scope
可選,表示影響的范圍、功能、模塊
subject
必填,簡(jiǎn)單說(shuō)明,不超過(guò) 50個(gè)字
body
選填,用于填寫更詳細(xì)的描述
footer
選填,用于填關(guān)聯(lián)issus
,或BREAK CHANGE
BREAKING CHANGE
必須是大寫,表示引入了破壞性 API 變更,通常是一個(gè)大版本的改動(dòng),BREAKING CHANGE:
之后必須提供描述,下面一個(gè)包含破壞性變更的提交示例
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
更詳細(xì)的說(shuō)明請(qǐng)看約定式提交規(guī)范
如何約束規(guī)范
怎么確保每個(gè)提交都能符合規(guī)范呢,最好的方式就是通過(guò)工具來(lái)生成和校驗(yàn),commitizen
是一個(gè)nodejs命令行工具,通過(guò)交互的方式,生成符合規(guī)范的git commit,界面如下:
開(kāi)始安裝:
# 全局安裝
npm install -g commitizen
# 或者本地安裝
$ npm install --save-dev commitizen
# 安裝適配器
npm install cz-conventional-changelog
packages.json
在配置文件中指定使用哪種規(guī)范
...
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
安裝完成后可以使用git cz
來(lái)代替git commit
,然后根據(jù)提示一步步輸入即可
格式校驗(yàn)commitlint
可能你不想每次都通過(guò)交互界面來(lái)生成,還是想使用git commit -m 'message'
,那么為了確保信息的正確性,可以結(jié)合husky
對(duì)提交的信息進(jìn)行格式驗(yàn)證
安裝依賴
npm install --save-dev @commitlint/{config-conventional,cli}
# 安裝husky
npm install --save-dev husky
添加 commitlint.config.js
文件到項(xiàng)目
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
?```
`package.json`配置
#git提交驗(yàn)證
“husky”: {
“hooks”: {
“commit-msg”: “commitlint -E HUSKY_GIT_PARAMS”
}
},
OK到這一步就完成了,最后給你項(xiàng)目 README.MD 加上一個(gè)commitizen-friendly
的標(biāo)識(shí)吧
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg) _blank](http://commitizen.github.io/cz-cli/)
## 自動(dòng)版本管理和生成CHANGELOG
規(guī)范化的提交信息除了能很好描述項(xiàng)目的修改,還有一個(gè)很好的作用就是能根據(jù)提交記錄來(lái)生成CHANGELOG.MD和自動(dòng)生成版本號(hào)等功能。
### standard-version
一個(gè)用于生成`CHANGELOG.md`和進(jìn)行`SemVer(語(yǔ)義化版本號(hào))`發(fā)版的命令行工具
主要功能:
* 自動(dòng)修改最新版本號(hào),可以是`package.json`或者自定義一個(gè)文件
* 讀取最新版本號(hào),創(chuàng)建一個(gè)最新的`git tag`
* 根據(jù)提交信息,生成`CHANGELOG.md`
* 創(chuàng)建一個(gè)新提交包括 `CHANGELOG.md`和`package.json`
### 語(yǔ)義化版本控制(SemVer)
先簡(jiǎn)單了解下什么是語(yǔ)義化的版本控制,其是由`GitHub`發(fā)起的一份用于規(guī)范版本號(hào)遞增的規(guī)則,
##### 版本格式
主版本號(hào).次版本號(hào).修訂號(hào),版本號(hào)遞增規(guī)則如下:
* 主版本號(hào)(major):當(dāng)你做了不兼容的 API 修改,
* 次版本號(hào)(minor):當(dāng)你做了向下兼容的功能性新增,可以理解為Feature版本,
* 修訂號(hào)(patch):當(dāng)你做了向下兼容的問(wèn)題修正,可以理解為Bug fix版本。
先行版本號(hào)可以加到“主版本號(hào).次版本號(hào).修訂號(hào)”的后面,作為延伸。
##### 先行版本
當(dāng)即將發(fā)布大版本改動(dòng)前,但是又不能保證這個(gè)版本的功能 100% 正常,這個(gè)時(shí)候可以發(fā)布先行版本:
* alpha: 內(nèi)部版本
* beta: 公測(cè)版本
* rc: 候選版本(Release candiate)
比如:1.0.0-alpha.0,1.0.0-alpha.1,1.0.0-rc.0,1.0.0-rc.1等。
`standard-version` 會(huì)根據(jù)提交的信息類型來(lái)自動(dòng)更改對(duì)應(yīng)的版本號(hào),如下:
* feat: 次版本(minor)+1
* fix: 修訂號(hào)(patch) +1
* BREAK CHANGE: 主板號(hào)(marjor) +1
> `standard-verstion` 生成的`CHANGELOG`只會(huì)包含`feat`,`fix`,`BREACK-CHANGE`類型的提交記錄
#### 使用
?``` bash
npm i --save-dev standard-version
添加npm script
{
scripts:{
"release": "standard-version",
"release:alpha": "standard-version --prerelease alpha",
"release:rc": "standard-version --prerelease rc"
}
}
執(zhí)行:
# npm run script
npm run release
# or global bin
standard-version
或者你想指定發(fā)行版本號(hào):
#指定類型 patch/minor/marjor
npm run release -- --release-as patch
#指定版本號(hào)
npm run release -- -- release-as 1.1.0
生命周期
prerelease
:所有腳本執(zhí)行之前prebump
/postbump
: 修改版本號(hào)之前和之后prechangelog
/postchangelog
:生成changelog
和生成changelog
之后pretag
/postag
:生成tag標(biāo)簽和之后
standard-version
本身只針對(duì)本地,并沒(méi)有push
才操作,我們可以在最后一步生成 tag
后,執(zhí)行 push
操作,在paceage.json
中添加
"standard-version": {
"scripts": {
"posttag": "git push --follow-tags origin master && npm publish"
}
}
還有更多配置功能自行查閱 官方文檔
其它類似工具
除了standard-version
,還有其它類似的工具,有興趣可以去了解下
修改Git Commit
為了使CHANGELOG.MD
更能加直觀看到每個(gè)版本的修改,我們盡量保證每次提交都是有意義的,但實(shí)際開(kāi)發(fā)過(guò)程中,不可避免會(huì)提交了一些錯(cuò)誤的 commit message,下面介紹幾個(gè)git
命令來(lái)修改commit
1 修改最后一次提交
git commit --amend
該命令會(huì)創(chuàng)建一個(gè)提交并覆蓋上次提交,如果是因?yàn)閷戝e(cuò)或者不滿意上次的提交信息,使用該命令就非常適合。
2 合并多條提交
git reset --soft [commitID]
如果你想合并最近幾條提交信息的話,那么就需要使用上面的命令來(lái)操作,指定要撤銷的 ccommitId ,該命令會(huì)保留當(dāng)前改動(dòng)并撤銷指定提交后的所有commit記錄,如果不指定ID的話可以使用HEAD~{num}
來(lái)選擇最近{num}
條提交
git reset --soft HEAD~2 #合并最近兩條提交
git commit -m 'feat: add new feat'
帶
--soft
參數(shù)的區(qū)別在于把改動(dòng)內(nèi)容添加到暫存區(qū) 相當(dāng)于執(zhí)行了git add .
git rebase -i
git rebase
的功能會(huì)更加強(qiáng)大,如果我想修改最近3條提交記錄,執(zhí)行
git rebase -i HEAD~3
會(huì)出現(xiàn)如下編輯器界面(vim編輯器):
上面顯示的是我最近 3條提交信息 ,下面是命令說(shuō)明,
修改方式就是將 commit
信息前的pick
改為你需要的命令,然后退出:wq
保存
下面是常用的命令說(shuō)明:
p,pick = 使用提交
r,reword = 使用提交,但修改提交說(shuō)明
e,edit = 使用提交,退出后使用git commit --amend 修改
s,squash = 使用提交,合并前一個(gè)提交
f,fixup = 和squash相同,但丟棄提交說(shuō)明日志
d,drop = 刪除提交,丟棄提交記錄
最后
文本主要介紹了如何規(guī)范git commit
和自動(dòng)語(yǔ)義化版本管理,以及如何修改git commit
,遵循一個(gè)規(guī)范其實(shí)沒(méi)比之前隨意填寫信息增加多少工作量,但依賴規(guī)范卻可以實(shí)現(xiàn)更多提升效率的事情。
參考
相關(guān)閱讀
- git使用手冊(cè)
- Git 教程
- GitHub 官方幫助文檔中文版
- Github 教程
- GitHub 2020精選實(shí)戰(zhàn)項(xiàng)目
- GitHub 優(yōu)質(zhì)開(kāi)源項(xiàng)目與資源 2020版
- GitHub 中國(guó)開(kāi)發(fā)者榜單 TOP200
- GitHub 全球開(kāi)發(fā)者榜單 TOP200
作者:eijil
來(lái)源:凹凸實(shí)驗(yàn)室