前言
最近心血来潮打算用vue3+ts写一个背诗的h5(为满足自己的背诗习惯)。工欲善其事,必先利其器。先搭个架子啦!虽然是自己一个人写的项目,但是该有的开发规范也是要有的哦!在弄commit规范和自动生成changlog的时候,因为我想要提交表情开头的commit格式而踩尽无数坑!!!故写此文纪念~ 哦!不~ 是归纳总结分享给身边所有想踩坑的人们儿~ 好啦!废话不多说,正式开始我的表演~😝
Commit 规范说明
首先,规范的commit信息能让人一眼清晰明了的知道该提交属于什么类型、修改范围、具体改动,提高团队协作。也方便我们日后找bug,提高团队协作。
下面让我们先来了解下目前大家使用较多的Angular团队规范。
Angluar commit message 规范
该规范将commit信息分为header、body、footer三个部分。
这三部分中哪一行都不能超过100个字符!(angular规范文档中写的)
这里说明下为什么要限制字符长度,因为git会将commit的主题部分超过72个字符的截断显示。效果如下图所示例:
Angluar commit message格式如下:
<type>(<scope>): <subject> // 这一行是Header
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
复制代码
Body部分比较简单, 为选填项, 指本次提交的具体描述。
Header部分
该规范将 header 分为 type、scope、subject 三部分。
type
type指本次提交的类型,为必填项,必须为以下之一:
- feat: 一项新功能
- fix: 一个错误修复
- docs: 仅文档更改
- style: 不影响代码含义的更改(空白,格式,缺少分号等)
- refactor: 既不修正错误也不增加功能的代码更改(重构)
- perf: 改进性能的代码更改
- test: 添加缺失或更正现有测试
- build: 影响构建系统或外部依赖项的更改(gulp,npm等)
- ci: 对CI配置文件和脚本的更改
- chore: 更改构建过程或辅助工具和库,例如文档生成
scope
scope指本次提交的影响范围,为可选项,可以是指定提交更改位置的任何内容。我一般都写更改部分的模块名或者文件名。
当更改影响的范围不止一个范围时,可以使用星号(*)。当然也可以不填写。
subject
subject指本次提交的简要描述,它有如下两个规则。
- 不要大写第一个字母
- 末尾没有点(.)
Footer部分 选填 可以包含以下两种情况
- 是否产生了破坏性修改
如果当前代码与上一个版本不兼容,如版本升级、接口参数减少、接口删除、迁移等就是破坏性修改。
如果是破坏性修改则 Footer 部分会以BREAKING CHANGE开头,后面是对变动的描述、以及变动理由和迁移方法。如下:
BREAKING CHANGE: 变动的描述\理由\迁移方法
复制代码
- 关闭 Issue 如果当前 commit 针对某个 issue,那么可以在 Footer 部分关闭这个 issue,也可以关闭多个 issue。填写格式如下:
Close #ISSUE_ID
Closes #ISSUE_ID, #ISSUE_ID
复制代码
如果你使用jira,也可以填写本次修改所影响的JIRA_ID,但是要开启该功能需要先集成 jira与gitlab集成 & jira与github集成。填写格式如下:
re #JIRA_ID // re是关于的意思
fix #JIRA_ID
复制代码
按照以上的格式提交到git上显示如下:
以上是Angular团队的commit规范,大家也可以根据自己团队的习惯去自定义commit规范。
自定义 commit message 规范
这部分我就给大家介绍下,我在这次项目里想要自定义的提交格式,大家可以举一反三。
我想自定义的规范是基于Angluar规范的,只是在它的基础上加个表情gitmoji字段在最打头的位置。格式如下:
:gitmoji: <type>(<scope>): <subject> // 这一行是Header
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
复制代码
其中gitmoji项是必填的,值只能为gitmoji提供的表情列表中的表情。
按照我想要的格式提交到git上显示如下:
这里先说一下,Angluar规范里也有写表情的,要借助 git-cz, 它是在subject打头显示的表情,跟我想要的效果不符合😀,是长这个样子滴!
到这里,commit规范格式也讲的差不多啦!这么多乱七八糟的规矩,当然不能让大家手写的啦!🎉🎉🎉🎉当当当当~ 让我们用工具来玩吧!
Commit 规范工具
这里,我们先聊怎么用工具实现 Angluar 默认规范的那种,后面再讲自定义的。 不管是 Angluar 版还是自定义版我们都会需要到下面这个工具:
commitizen:它会提供 git cz 命令替代我们的 git commit命令,帮助我们更加方便生成符合规范的 commit message。
Angluar 规范版
全局安装
npm install -g commitizen
复制代码
初始化 commitizen 预设,这里使用官网首选的预设 cz-conventional-changelog
cz-conventional-changelog: 它是 commitizen 的首选适配器,默认有配置,但也可以自定义types,设置header长度之类的属性等。但是它的提示信息都是英文的,不能自定义配置(源码内发现的)。如果需要自定义配置提示信息需要使用 cz-customizable 适配器,文章后面自定义版有这部分内容,点击这里传送。
commitizen init cz-conventional-changelog --save-dev --save-exact
复制代码
全局模式下, 需要 ~/.czrc 配置文件, 为 commitizen 指定 Adapter
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
复制代码
现在大家现在就可以使用 git cz 或 cz 命令来提交commit信息了。
全局安装的可以在任何git init下的目录执行 git cz 或 cz 命令代替 git commit 。
项目内安装
npm install commitizen cz-conventional-changelog -D
复制代码
在package.json中配置,这里是将 cz-conventional-changelog 设置为 commitizen 的 Adapter 。大家也可以选择其他的 Adapter ,文章内自定义版有设置其他 Adapter 的 点击此处查看 。
"scripts": {
"commit": "cz"
}
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
复制代码
项目内安装,只能在当前项目目录下 npm run commit 代替 git commit。
我为了方便用cz命令,都是全局和项目内都安装,下面演示一下效果:
到这里,就已经实现commit提交自动化了。不过cz-conventional-changelog并没有支持表情,下面我们讲一下怎么加入表情。
表情在subject部分开头的显示
表情在subject部分开头,也可以没有表情,提交效果如下:
实现这种效果,需要用到 streamich/git-cz
1、全局安装
可以不用下载 commitizen ,就可以运行git-cz命令提交commit,如果已经安装了 commitizen 会覆盖 commitizen 的 git cz命令的效果。
npm install -g git-cz
git-cz
复制代码
2、搭配 commitizen 项目内使用
npm install -D git-cz
复制代码
package.json 中 commitizen 的适配器为 git-cz:
{
"config": {
"commitizen": {
"path": "git-cz"
}
}
}
复制代码
运行以下命令
npx git-cz
复制代码
效果如下,提交的commit在subject开头有表情:
😭我的电脑表情显示乱码,还没有解决(有知道怎么解决的朋友麻烦评价区告诉我,我实在是搞不出来了😰),不过只是电脑上乱码显示,到github上看是正常显示的,所以也并不会很妨碍我提交,只是看着心里不得劲。
这里还有个小问题,在我实际操作中,发现只要 install 了 git-cz 就可以运行 npx git-cz 命令,显示的选择文本等也是符合git-cz默认设置的,不需要 package.json 设置配置器,不知道为什么跟官网描述不一致,还没弄清楚😥。
git-cz 工具它也是提供自定义配置的,但是配置项有限。在根目录添加 changelog.config.js ,下面为大家示例一个官方配置,大家可以在streamich/git-cz官方看更多配置。
./changelog.config.js
module.exports = {
"disableEmoji": false,
"list": [
"test",
"feat",
"fix",
"chore",
"docs",
"refactor",
"style",
"ci",
"perf"
],
"maxMessageLength": 64,
"minMessageLength": 3,
"questions": [
"type",
"scope",
"subject",
"body",
"breaking",
"issues",
"lerna"
],
"scopes": [],
"types": {
"chore": {
"description": "Build process or auxiliary tool changes",
"emoji": "🤖", // 当前类型的commit所显示的表情
"value": "chore"
},
"ci": {
"description": "CI related changes",
"emoji": "🎡",
"value": "ci"
},
"docs": {
"description": "Documentation only changes",
"emoji": "✏️",
"value": "docs"
},
"feat": {
"description": "A new feature",
"emoji": "🎸",
"value": "feat"
},
"fix": {
"description": "A bug fix",
"emoji": "🐛",
"value": "fix"
},
"perf": {
"description": "A code change that improves performance",
"emoji": "⚡️",
"value": "perf"
},
"refactor": {
"description": "A code change that neither fixes a bug or adds a feature",
"emoji": "💡",
"value": "refactor"
},
"release": {
"description": "Create a release commit",
"emoji": "🏹",
"value": "release"
},
"style": {
"description": "Markup, white-space, formatting, missing semi-colons...",
"emoji": "💄",
"value": "style"
},
"test": {
"description": "Adding missing tests",
"emoji": "💍",
"value": "test"
}
}
}
复制代码
这种 commit 不需要额外添加强制校验commit的工具,这个格式因为表情是属于 subject 字段的,所以是符合 angluar 规范的,默认用 angluar 的校验是可以通过的。所以有的人想要表情commit是用 commitizen+git-cz 实现的。
表情在提交信息最开头显示
这里,我先介绍一个 commitizen 官网推荐的一个适配器 cz-emoji,但我这个主题不是讲它。它提交的commit信息如下:
cz-emoji:这个适配器是将type部分替换成emoji了。由于这个比较简单,大家感兴趣去看它的官网说明吧,这里不讨论如何使用这个了。
好了,这里主要讲如何在 angluar 基础上加入表情,保留type的情况,在type前面加入表情 :emoji:(这个是我自己搞了好半天的😂)。这个commit规范就是我上面提到的表情开头规范
来吧,先让俺们安装 cz-customizable
npm i -D cz-customizable
复制代码
package.json
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
}
复制代码
cz-customizable:这个是适配器用于自定义 cz 命令的,可以自定义提示信息、types、长度等等。
在项目根目录下添加 .cz-config.js 添加配置项即可,大家可以参考官网说明配置属于自己项目的提示和规则,我的配置文件如下:
/.cz-config.js
module.exports = {
types: [
{
value: 'feat',
name: 'feat: 新功能'
},
{
value: 'fix',
name: 'fix: 修复bug'
},
{
value: 'init',
name: 'init: 初始化'
},
{
value: ':pencil2: docs',
name: 'docs: 文档变更'
},
{
value: 'style',
name: 'style: 代码的样式美化'
},
{
value: 'refactor',
name: 'refactor: 重构'
},
{
value: 'perf',
name: 'perf: 性能优化'
},
{
value: 'test',
name: 'test: 测试'
},
{
value: 'revert',
name: 'revert: 回退'
},
{
value: 'build',
name: 'build: 打包'
},
{
value: 'chore',
name: 'chore: 构建/工程依赖/工具'
},
{
value: 'ci',
name: 'ci: CI related changes'
}
],
messages: {
type: '请选择提交类型(必填)',
customScope: '请输入文件修改范围(可选)',
subject: '请简要描述提交(必填)',
body: '请输入详细描述(可选)',
breaking: '列出任何BREAKING CHANGES(可选)',
footer: '请输入要关闭的issue(可选)',
confirmCommit: '确定提交此说明吗?'
},
allowCustomScopes: true,
allowBreakingChanges: ['feat', 'fix'], // 当提交类型为feat、fix时才有破坏性修改选项
subjectLimit: 72
};
复制代码
现在输入 cz 或 git cz ,效果如下:
因为,我想要表情开头,所以我用了个取巧的办法将 .cz-config.js 的 types 字段修改为下面这个样子来实现:
types: [
{
value: ':zap: feat',
name: '⚡ feat: 新功能'
},
...
]
复制代码
效果如下,就是加入了表情部分,其它跟上面那个效果一样,就不录gif图了:
将value部分绑定上表情码就会带上表情了,用表情码 :zap: 不用⚡ 是因为之后咱们还需要加入校验commit信息,校验表情的预设只有是表情码能通过校验。咱们自定义这种格式是不符合 angluar 规范的,需要安装其他校验工具。马上就要讲到啦!
这里的表情都是用的 gitmoji 里提供的表情,以及后面强制校验commit信息表情也是校验是否包含在这个里面的表情。这个表情码在命令行中显示的还是表情码,提交到 github 上面后就会显示对应的表情的。如下图:
vscode提交代码工具
可能你懒得敲命令去提交commit,这里推荐两个我个人觉得还可以的vscode提代码的插件,直接在扩展商店里搜了安装就行,用法很简单就不说,大家下载的时候读一下 Usage 就会了。(之后我会自己写一个符合自己commit习惯的vscode插件,到时候推荐给大家)😁
Visual Studio Code Commitizen Support:这个插件是我一直用习惯了的,它遵循cz-customizable并创建所需的配置文件,如果你的项目根目录有 .cz-config.js 配置,它会根据这个配置文件显示提示和校验规则(需要重启下vscode才会生效)。此插件提交效果如下:
Conventional Commits:这个插件可以填表情(选填),格式是符合 angluar 或 angluar+subject加表情 规范的。此插件提交效果如下:
规范校验
上面提代码的工具,虽然可以让大家方便的提代码,but!如果你们团队的人就是不遵守规范提代码怎么办呢?是时候请出 husky commitlint 登场啦!他们可以在你commit的时候校验你的commit信息是否是规范的,如果不是就提交不了。
这部分,也是分为 angluar版和自定义表情版展开,首先,不管说明版本都需要安装这两个工具:
husky:顾名思义,哈士奇,哈哈,咬住你不放。这个工具是用来在git钩子里运行命令有问题咬住你过不去钩子的。一般用来执行eslint、run test、commitlint 相关命令的。
commitlint:这个就没啥好说的了,就是校验你的commit信息的,提供多种共享配置。
Commit message 校验
首先,下载 husky & commitlint。
npm i -D husky commitlint
复制代码
新建一个 .commitlintrc.js 或 commitlint.config.js。commitlint会找到这个文件,按文件中指定的 extends 去校验 commit 信息。也可以自定义设置一些规则。
angluar 版
校验 angluar commit规范信息的,内容如下:
/.commitlintrc.js
module.exports = {
extends: ['@commitlint/config-conventional']
};
复制代码
@commitlint/config-conventional是按 angluar 规范校验的,大家也可以用其他的,或者自己写一个lint发到npm上。
emoji 开头版
校验我上面提的 emoji 开头的commit规范信息,commitlint 并没有内置合适的共享配置,这种需要自己写一个符合的配置,好在已经有人写过这种可共享配置了,这里我用的网上找到的空谷大佬写好的 commitlint-config-gitmoji。
npm i -D commitlint-config-gitmoji
复制代码
内容如下:
/.commitlintrc.js
module.exports = {
extends: ['gitmoji']
};
复制代码
commitlint都设置好了,下面我们要实现提交时强制校验。
husky强制校验commit信息
执行以下命令,会在项目根目录下生成一个.kusky文件夹。(这里默认大家下的husky都是最新的5.0版本)
npx husky install
复制代码
在.husky文件夹内创建commit-msg文件(注意不要建到husky/_那个文件夹里去了),内容如下:
#!/bin/sh
npx --no-install commitlint --edit "$1"
复制代码
这个时候,我们再提交代码的时候会走到commit-msg这个钩子里,执行我们写好的校验commit的命令,当commit信息不符合规范时,commitlint会提示哪里规则不对,husky会拦住当前commit信息提不上了。就实现了强制遵守定义好的commit规范,不能随便瞎提代码了!!!
下面,我们再聊下在commit之前校验代码和跑测试。
代码规范校验 & 跑测试
虽然咱们编辑器都有eslint插件自动修复代码,大家一般也都不会提交不符合eslint的代码,但是有的同学可能真的不装这个插件没有自动修复,不看效果盲写代码提交的,所以以防万一都是需要在commit前校验代码规范以及测试的,这样保证你提的代码都是正儿八经的符合规范的并且通过测试的🤣,哈哈哈哈!!!
首先,咱们需要安装 lint-staged,很多人不用 lint-staged,直接在 pre-commit 钩子里执行 npm run lint,这样有个问题,如果项目大了,你只修改一个文件,但它仍然会校验src下所有文件,就会导致提个代码慢的要死等半天。而 lint-staged 就能解决这个问题,它只会校验你修改的那部分文件。好了,了解前因后果后我们开始吧~
npm i -D lint-staged
复制代码
package.json
"scripts": {
"lint": "vue-cli-service lint --fix",
"test": "your-cmd"
},
"lint-staged": {
"src/**/*.scss": [
"stylelint --fix"
],
"src/**/*.{js,vue,ts,tsx}": "npm run lint"
}
复制代码
在.kusky文件夹内创建pre-commit文件,内容如下:
#!/bin/sh
npx --no-install lint-staged
npm run test
复制代码
在这里,当你提交代码就会自动校验并修复你的所提交的代码。下面,我们开始讲 CHANGELOG 自动生成。
CHANGELOG 自动生成
CHANGELOG 大概的样子长这个样:
首先,聊一下什么是 CHANGELOG ,为什么需要 CHANGELOG ?它记录你项目所有的commit信息并归类版本,可以快速跳转到该条commit记录,甚至可以显示修改人信息一眼发现bug的创建者😂。它能让你方便知道项目里哪个版本做了哪些功能有哪些bug等信息。也方便排查bug,对于提交记录一目了然,不用一个一个去翻去查。
这里,就直接用 standard-version 来实现自动生成 CHANGELOG 了。 conventional-changelog 咱们就不聊了,毕竟是它推荐咱们用 standard-version (这都是同一个团队的东西,基于conventional-changelog实现的)。关于为什么推荐 standard-version,大家自行阅读官方解释吧! 官方地址给大家。
semantic-release 也不聊了,因为 CI/CD 我没咋研究过,没法聊😂!官方地址在此,还有一篇推荐文章大家有兴趣的可以读读。
好了,我们开始用 standard-version 来实现吧!先来下载~
npm i -D standard-version
复制代码
package.json
{
"scripts": {
"release": "standard-version"
}
}
复制代码
执行以下命令,就会根据你的commit信息自动生成 CHANGELOG.md 文件。
npm run release
复制代码
当你的commit type是 feat和fix的时候执行这个命令,它会自增版本号。
这里说个我调试中发现的小问题,在你执行过一次后如果你删掉了 CHANGELOG.md 文件,并且没有再修改提交,再重新去执行生成命令,它会给你生成只有一个版本号信息的文件,你必须提交一下再执行才会有commit日志,但在这个提交之前的那些记录不会再显示(很奇怪,调试的时候注意下这个问题)。
standard-version 提供自定义配置不同类型对应显示文案,在根目录新建 versionrc.js 文件,这里我示例一个我的 versionrc.js 内容:
module.exports = {
"types": [
{ "type": "feat", "section": "✨ Features | 新功能" },
{ "type": "fix", "section": "🐛 Bug Fixes | Bug 修复" },
{ "type": "init", "section": "🎉 Init | 初始化" },
{ "type": "docs", "section": "✏️ Documentation | 文档" },
{ "type": "style", "section": "💄 Styles | 风格" },
{ "type": "refactor", "section": "♻️ Code Refactoring | 代码重构" },
{ "type": "perf", "section": "⚡ Performance Improvements | 性能优化" },
{ "type": "test", "section": "✅ Tests | 测试" },
{ "type": "revert", "section": "⏪ Revert | 回退" },
{ "type": "build", "section": "📦 Build System | 打包构建" },
{ "type": "chore", "section": "🚀 Chore | 构建/工程依赖/工具" },
{ "type": "ci", "section": "👷 Continuous Integration | CI 配置" }
]
}
复制代码
配置之后,我的 CHANGELOG 就长这个样子啦!
这里得提一下, standard-version 默认的预设是 angular ,像咱们之前自定义表情那种commmit,规范和angular不一样,它读不到对应的type生成的更改日志是没法分类的,上面写 commitlint-config-gitmoji 工具的大哥已经写了根据 :emoji: type: … 格式生成 CHANGELOG 的工具conventional-changelog-gitmoji-config了,这里咱们就直接用吧!不过这个工具并没有提供自定义配置类型文案的功能,在源码里写死了,所以用了这个工具不能像上面那样 versionrc.js 自定义了,不过它自带的也挺好看的,可以设置显示表情,还支持中英文两种,还支持显示修改人和邮箱,也是很强大的!!!🉑
来,咱们下载先~
npm i -D conventional-changelog-gitmoji-config
复制代码
standard-version 通过 --preset 命令另外指定预设(源码内发现)
{
"scripts": {
"release": "standard-version --preset gitmoji-config"
}
}
复制代码
这里解释一下,为什么 --preset gitmoji-config 就可以读到预设,这个包明明叫 conventional-changelog-gitmoji-config 啊,这是因为 conventional-changelog-preset-loader找预设时找的是 conventional-changelog-xxx,前缀是写死的 conventional-changelog-,源码截图在此:
CI/CD没搞过,也没用上 standard-version,为了方便我就直接在 pre-push 钩子里执行生成 CHANGELOG 的命令了哈~
.husky/pre-push
#!/bin/sh
npm run release
复制代码
这样,当我执行 git push 的时候,就会自动生成 CHANGELOG.md 一并提交到远端了,就不用手动执行 npm run release 命令再push了。啦啦啦🎈🎈🎈
终于结束啦!感谢大家听我啰嗦了这么久,希望可以帮到大家,如果文章中有错漏之处还望指正。谢谢大家啦!!!😜
参考文献
以及文中各个工具的文档和源码,就不一一罗列了