如何规范git commit提交
相信很多人使用SVN、Git等版本控制工具时候都会觉得每次提交都要写一个注释有什么用啊?好麻烦,所以我每次都是随便写个数字就提交了,但是慢慢的我就发现了,如果项目长期维护或者修改很久之前的项目,没有一个清晰明了的注释是多么的DT,我就经历过找回自己之前被修改的代码,然后看到自己写的git commit 瞬间崩溃了,真是自己选的路跪着也要走完呀!于是我就想规范一下自己,所以在网上搜罗了一些相关文章,总结了一下。
展示一下曾经我错误的style:
一、规范git分支
请移步相关文章:git项目分支管理
二、做好提交前的Code Review
何时做Code Review ?
在向 master 、 develop 、 bugfix 提交Merge Request 的时候做Code review,在存在以下问题时会拒绝合并并且给出修改意见:
- 代码不符合约定的规范
- 代码有更好的实现方式
- 边界条件错误
Git hook可以做一些什么?
- 前端eslint 、stylelint 代码规范检测
- git commit 规范检测
在Cube 项目,写好关键字和简短描述,请勿提交无实际内容的commit msg
简化为
<type>(<scope>): <subject>
下面就介绍一下如何用Git hook进行操作。
相关代码检测请移步对应文章:
下面是怎样进行git commit 规范检测
Commit Message 格式
要想规范git commit 提交,我们先要了解一下Commit Message格式,目前规范使用较多的是 Angular 团队的规范, 继而衍生了 Conventional Commits specification. 很多工具也是基于此规范, 它的 message 格式如下:
每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。
<type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer>
其中,Header 是必需的,Body 和 Footer 可以省略。
不管是哪一个部分,任何一行都不得超过100个字符。这是为了避免自动换行影响美观。
- 标题行(第一行/header): 必填, 描述主要修改类型和内容
- 主题内容(body): 描述为什么修改, 做了什么样的修改, 以及开发的思路等等
- 页脚注释(footer): 放 Breaking Changes 或 Closed Issues
- scope: commit 影响的范围, 比如: route, component, utils, build...
- subject: commit 的概述, 建议符合 50/72 formatting
- body: commit 具体修改内容, 可以分为多行, 建议符合 50/72 formatting
- footer: 一些备注, 通常是 BREAKING CHANGE 或修复的 bug 的链接.
注:该工具要输入时都可以用\n 来换行操作, 回车直接结束描述!!如果想结束重来可以使用ctrl + c
Header
Header部分只有一行,包括三个字段:type
(必需)、scope
(可选)和subject
(必需)。
type(必填):
type
用于说明 commit 的类别。
-
feat:新增功能
-
fix:bug 修复
-
docs:文档更新
-
style:不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑)
-
refactor:重构代码(既没有新增功能,也没有修复 bug)
-
perf:性能, 体验优化
-
test:新增测试用例或是更新现有测试
-
build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
-
ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
-
chore:不属于以上类型的其他类,比如构建流程, 依赖管理
-
revert:回滚某个更早之前的提交
如果type
为feat
和fix
,则该 commit 将肯定出现在 Change log 之中。其他情况(docs
、chore
、style
、refactor
、test
)由你决定,要不要放入 Change log,建议是不要。
scope(可选):
scope
用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
subject(必填):
subject
是 commit 目的的简短描述,
- 以动词开头,使用第一人称现在时,比如
change
,而不是changed
或changes
- 第一个字母小写
- 结尾不加句号(
.
)
Body(可省)
Body 部分是对本次 commit 的详细描述,可以分成多行。
有两个注意点。
(1)使用第一人称现在时,比如使用change
而不是changed
或changes
。
(2)应该说明代码变动的动机,以及与以前行为的对比。
Footer(可省)
Footer 部分只用于两种情况。
1)不兼容变动
如果当前代码与上一个版本不兼容,则 Footer 部分以BREAKING CHANGE
开头,后面是对变动的描述、以及变动理由和迁移方法。
2)关闭 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替代你的 git commit (使用工具生成符合规范的commit message)
上面我们已经了解了Commit Message的格式是什么样的了,如果让我们自己手动敲出那些格式也不是不可能,但是我相信那不是程序员的作风,大多数人会疯掉吧,,那么就需要通过commitizen/cz-cli 工具,我们需要借助它提供的 git cz 命令替代我们之前的 git commit 命令, 帮助我们生成符合规范的 commit message .
安装命令如下。
npm install --save-dev commitizen
初始化项目以使用cz-conventional-changelog适配器
commitizen init cz-conventional-changelog --save-dev --save-exact
因为commitizen工具是基于Node.js的,对于没有package.json文件的项目上面命令会不成功,所以先创建一个空的package.json文件,再执行上面命令即可,有package.json文件的项目可以忽略本条命令。
npm init --yes
至此就算完整的安装完了,之后在需要 git commit 的地方更换成 git cz 指令,这是就会出现选项,用来生成符合格式的Commit message.
使用commitlint工具检验commit格式是否符合规范
#安装commitlint cli和传统配置
npm install --save-dev @commitlint/{config-conventional,cli}
#对于Windows:
npm install --save-dev @commitlint/config-conventional @commitlint/cli
#配置commitlint使用传统的config配置文件,在项目根目录生成就可以了
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
在刚刚生成的配置文件commitlint.config.js制定提交message规范
/** * feat:新增功能 * fix:bug 修复 * docs:文档更新 * style:不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑) * refactor:重构代码(既没有新增功能,也没有修复 bug) * perf:性能, 体验优化 * test:新增测试用例或是更新现有测试 * build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交 * ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交 * chore:不属于以上类型的其他类型,比如构建流程, 依赖管理 * revert:回滚某个更早之前的提交 */ module.exports = { extends: ['@commitlint/config-conventional'] }; module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', [ "feat", "fix", "docs", "style", "refactor", "test", "chore", "revert" ]], 'subject-full-stop': [0, 'never'], 'subject-case': [0, 'never'] } };
rule配置说明 :rule由name和配置数组组成,如: name:[0, 'always', 72] ,数组中第一位为 level ,可选 0,1,2 ,0为禁用规则,1为警告,2为错误,第二位为应用与否,可选 always|never ,第三位该rule的值。
上面我们就完成了commitlint的安装与提交规范的制定。检验commit message的最佳方式是结合git hook,所以需要配合Husky。
什么是husky?(GitHook 工具 —— husky介绍及使用)
husky继承了Git下所有的钩子,在触发钩子的时候,husky可以阻止不合法的commit,push等等。注意使用husky之前,必须先将代码放到git 仓库中,否则本地没有.git文件,就没有地方去继承钩子了。安装husky
npm install --save-dev husky
在 package.json 文件通过字段直接添加git钩子。 husky.hooks
// package.json { "husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS," //commitlint检测 "pre-commit": "npm run stylelintt && npm run eslintt" //js、css检测,这两个检测需要自己配置,pre-commit会优先于commit-msg执行 } } }
这段配置告诉了 git hooks ,当我们在当前项目中执行 git commit -m '测试提交' 时将触发 commit-msg事件钩子 并通知husky
,从而执行 commitlint -E HUSKY_GIT_PARAMS 命令,也就是我们刚开始安装的 ./node_modules/.bin/commitlint ,它将读取 commitlint.config.js 配置规则并对我们刚刚提交的测试提交
这串文字进行校验,若校验不通过,则在终端输出错误,commit终止。
使用 commit-msg 给出了我们想要的东西:只要创建新的提交就会执行它。传递husky的 HUSKY_GIT_PARAMS 给 commitlint 通过 -E|--env 标记它引导到相关的编辑文件。默 -e 认为 .git/COMMIT_EDITMSG 。
测试
现在你可以自己手动提交 git commit -m "foo: this will fail" 如果不符合规则,自然就会报错,不通过了,这就是为什么要用 commitizen 代替 git commit的原因了,只要跟着commitizen 选择,把必填的都写上就不会报错,必然可以通过了。
生成 Change log
conventional-changelog 是一款可以根据项目的commit
和 metadata
信息自动生成 changelogs
和 release notes
的系列工具,并且在辅助 standard-version 工具的情况下,可以自动帮你完成生成version
、打tag
, 生成CHANGELOG
等系列过程。
conventional-changelog 生态主要模块
- conventional-changelog-cli - conventional-changelog 核心命令行工具
- standard-changelog - 针对 angular commit 格式的命令行工具
- conventional-github-releaser - 利用 git metadata 针对 Github 的发布工具
- conventional-commits-detector - commit message 规范引用检测
- commitizen - 针对开发者简单的 commit 规范
- commitlint - commit Lint 工具
安装
npm install -g conventional-changelog-cli
基本使用
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 -s -r 0" } }
以后,直接运行下面的命令即可。
npm run changelog
参考: