commitizen、commitlint、standard-version、convertional-changelog
这4个工具可以解决以下几个问题:
commitizen:自动化提示
commit message
commitlint:自动化校验
commit message
是否符合规范standard-version:自动更新
package.json
里的版本号conventional-changelog:自动生成
changelog
,更好的维护版本迭代
一个一个安装和配置太麻烦,所以我将这4个工具整合到一块,欢迎下载体验,点个Star~
npm地址:vue-cli-plugin-commitlint-release
github地址:vue-cli-plugin-commitlint-release
commitizen、commitlint
说 commitizen 之前,先聊一聊我们使用得最多但也很头疼的 commit message。
大家都知道,开发过程中的 commit message 具有记录当前代码概要的作用,备忘和查找起来都有很好的参考作用。如果随意书写,commit message 也就失去了它的意义所在。
想象中的 commit message 可能是这样的:
git commit -m "fix(xx项目): 修复了iOS键盘弹起失败的bug"
但现实却是这样的:
git commit -m "aaa"
正常人应该都猜不懂这是个啥意思,当事人当时可能还记得,过几天,他自己估计也不由得感叹:WTF?
commit mesaage 的重要性了解了,规范书写 commit message 的重要性也了解了,那就说说如何解决这个问题。那就引入一个commit message 规范?bingo~
commit message 规范
这里就介绍一个大众认可的规范 AngularJS's commit message convention,格式如下:
<type>(scope): <subject> // 空一行 <body> // 空一行 <footer>
整个 commit message 分为3部分:Header、Body 和 Footer。
其中,Header 是必需的,Body 和 Footer 可以省略。
不管是哪一个部分,任何一行都不得超过72个字符(或100个字符)。这是为了避免自动换行影响美观。
Header
Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。
type
type用于说明 commit 的类别,只允许使用下面7个标识。
feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改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 的详细描述,可以分成多行。
有两个注意点:
(1)使用第一人称现在时,比如使用change而不是changed或changes。
(2)应该说明代码变动的动机,以及与以前行为的对比。
Footer
Footer 部分只用于两种情况。
不兼容变动
如果当前代码与上一个版本不兼容,则 Footer 部分以BREAKING CHANGE开头,后面是对变动的描述、以及变动理由和迁移方法。
关闭 Issue
如果当前 commit 针对某个issue,那么可以在 Footer 部分关闭这个 issue ,也可以一次关闭多个 issue 。
具体规范和案例都可以参考:AngularJS's commit message convention。
commitizen
但问题来了,光有规范,就能解决上面那些问题吗?答案是否定的,依靠人工维护,成本高且风险高。
所以 commitizen 就出场了,一个自动提示的 commit message 的工具。
先看下效果:
直接 git cz,就会提示选择 type、输入 scope、subject 等,妈妈再也不用担心我写的 commit message 不符合规范啦。
具体的安装执行直接参考:commitizen,但有一点我想再提一下。
适配器选择
下载后默认的适配器是 streamich/git-cz
还有一种适配器是 AngularJS's commit message convention
一般选择都是 AngularJS 规范,所以这时候就需要切换适配器。
首先,我个人比较喜欢本地安装 commitizen
,喜欢全局安装的同志们可以使用 -g 去安装哈
npm i commitizen --save-dev
然后,执行下面的命令来自动安装 & 配置 cz-conventional-changelog
:
# npm ./node_modules/.bin/commitizen init cz-conventional-changelog --save-dev --save-exact # or npx npx commitizen init cz-conventional-changelog --save-dev --save-exact # or 如果你已经全局安装了 commitizen commitizen init cz-conventional-changelog --save-dev --save-exact
上面的命令做了两项操作:
通过
npm
安装了包依赖cz-conventional-changelog
。在
package.json
中自动配置了如下内容:
"config": { "commitizen": { "path": "./node_modules/cz-conventional-changelog" } }
其实完全可以自己手动来处理,首先安装依赖包:
npm i --save-dev cz-conventional-changelog
然后在 package.json
文件中加入上面的配置,结果是一样的。
最后运行 npx git-cz
(npm 5.2+),或加到 scripts 中,执行 npm run commit
"scripts": { "commit": "./node_modules/.bin/git-cz" }
commitlint
这时候问题又来了,有人就说,我就习惯了自己敲 git commit -m 命令,不想自动化提示,好麻烦。
完全没得问题,这时候 commitlint 就要出场了。保持 git commit -m 书写 commit message,但提交完,就会自动校验输入的 commit message 是否符合规范。
安装和使用都贼简单,三部曲:
安装
npm install --save-dev @commitlint/config-conventional @commitlint/cli husky
commitlint 配置文件:commitlint.config.js
然后在 package.json 中加入如下配置:
{ "husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } } }
其他注意事项请参考:commitlint
standard-version、convertional-changelog
上面说完了 commit message,现在就来说说 version 的修改,以及自动生成 changelog。
standard-version
大家有没有遇到过这样的场景,当你修改完代码,准备打 tag 的时候,需要纠结版本号的更新规则,而且还需要手动修改,有时候不小心就忘记了。
这时候 standard-version 就出场了,standard-version 使用 semver 和传统的提交消息,自动化版本控制和变更日志生成。
使用方法也很简单,2部曲:
# 安装 npm i --save-dev standard-version # 发布 npm run release -- --release-as minor
最后一个参数 minor,还总共有3种选择 [ major | minor | patch ],具体什么意思呢,以当前版本 1.0.0 为例:
major:主版本号,当你做了不兼容的 API 修改。这时候的 version 应该为 2.0.0。
minor:次版本号,当你做了向下兼容的功能性新增。这时候的 version 应该为 1.1.0。
patch:修订号,当你做了向下兼容的问题修正。这时候的 version 应该为 1.0.1。
其他的具体参考:standard-version
convertional-changelog
版本号修改好了,那怎么自动生成 changelog 呢?这时候 convertional-changelog 就出场了。
需要依赖 2种包:conventional-changelog 和 conventional-changelog-cli。
# 安装 npm i --save-dev conventional-changelog conventional-changelog-cli # 生成 changelog conventional-changelog -p angular -i CHANGELOG.md -s -r 0
执行命令太长,所以一般放到 scripts 中,直接运行 npm run changelog
即可。
"scripts": { "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0" }
执行完命令会生成一个 CHANGELOG.md 文件,就代表成功了。
4个工具的集合
先来说说从修改代码到生成 changelog 的工作流:
修改代码
提交代码:commitizen 或 commitlint
确保提交成功后,修改 package.json 里的版本号:standard-version
生成changelog,这时候会生成一个 CHANGELOG.md 文件:convertional-changelog
提交 package.json 和 CHANGELOG.md 文件
打 Tag
推到远程
一套流程下来,发现虽然有自动化,但被拆的细碎,反而越来越麻烦了,是不是还有一个更好的方法让整个流程更简单?答案是肯定的。这时候就需要一个自动化脚本将工作流串起来。
实现方式也很简单,具体参考:vue-cli-plugin-commitlint-release
实现思路:
修改代码和提交代码不变,后续的自动修改版本号、生成changelog、将 package.json 和 CHANGELOG.md 文件提到远程等步骤写到脚本里。
var inquirer = require('inquirer'); //命令行交互模块 var shell = require('shelljs'); // 判断是否支持 git if (!shell.which('git')) { shell.echo('Sorry, this script requires git'); shell.exit(1); } // 获取修改代码的等级,是 patch、minor,还是 major const getVersion = async () => { return new Promise((resolve, reject) => { //提示选择 [ patch | minor | major] inquirer.prompt([ { type: 'list', name: 'version', choices: ['patch', 'minor', 'major'], message: 'please choose argument [major|minor|patch]: ' } ]).then(answer => { resolve(answer.version); }).catch(err => { reject(err); }); } )} const main = async () => { const version = await getVersion(); await shell.exec(`npm run release -- --release-as ${version}`); await shell.exec('npm run changelog'); await shell.exec('git push --follow-tags origin master'); await shell.exec('git add -A'); await shell.exec(`git commit -m "docs(build): changelog"`); await shell.exec('git push'); } main()
至此,所有的工具就说完啦,有什么好的想法或建议都可以留言和我交流哦~
也欢迎大家去下载和使用这个自动化工具:vue-cli-plugin-commitlint-release
同时,有什么问题,也欢迎大家到 github 上提 issue:issues