项目集成之提交规范
在团队协作中尤其是对于大型项目,git规范提交在团队中发挥着重要的作用,如果没有统一的规范提交格式,提交信息多了将会显得杂乱无章,这对于后期维护或者是错误定位及回滚尤其是大型项目将是个灾难。拥有固定的提交规范格式将会一目了然,可以快速定位到想要找到的内容。下面就来看看如何在项目中规定提交的规范格式
约定式提交
约定式提交规范是一种基于提交信息的轻量级约定。 它提供了一组简单规则来创建清晰的提交历史; 这更有利于编写自动化工具。 通过在提交信息中描述功能、修复和破坏性变更, 目前最受欢迎的是 Angular规范
提交格式如下:
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
2
3
4
5
每次提交可以包含页眉(header)、正文(body)和页脚(footer),每次提交必须包含页眉内容,页眉的格式指定为提交类型(type)、作用域(scope,可选)和主题(subject)
提交类型
提交类型用来表示本次修改的类型,常见的有如下多种类型:
- feat:增加新的特征
- docs:对文档进行了修改
- fix:修复bug
- style:不影响代码含义的修改,比如空格、格式化、缺失的分号等
- test:增加确实的测试或者矫正已存在的测试
- refactor:既不是修复bug也不是添加特征的代码重构
- chore:构建过程或辅助工具的变动
作用域
用来指定本次修改的范围,如:component、config、docs等等
主题
主题通常用简洁描述概括本次修改的内容
Breaking Changes
不兼容修改指的是本次提交修改了不兼容之前版本的API或者环境变量,所有不兼容修改都必须在页脚中作为中断更改块提到,以BREAKING CHANGE:开头,后跟一个空格或者两个换行符,其余的信息就是对此次修改的描述,修改的理由和修改注释
关联issue
如果本次提交目的是修改issue的话,需要在页脚引用该issue,如修复bug:
Closes #1, #2
作用
对于团队协作而言,约定式提交的作用主要体现在以下几个方面:
- 统一提交信息格式:团队成员遵循相同的提交信息格式,从而使提交历史更加整洁、一致。这有助于提高项目的可读性和可维护性
- 提高代码审查效率:规范的提交信息可以帮助团队成员更快地理解每次提交的目的和更改内容。这可以提高代码审查的效率,减少沟通成本
- 便于生成版本日志:遵循一致的提交信息规范可以使生成版本日志变得更加容易。一些工具(如 semantic-release)可以自动根据提交信息生成版本日志
- 提高团队协作水平:帮助团队成员养成良好的编码习惯,培养一致的协作风格。这有助于提高团队的整体协作水平和项目成功率
CommitLint
commitlint 是一个用于规范 Git 提交信息的工具。它可以帮助团队遵循一致的提交信息规范,从而提高代码库的可读性和可维护性。使用 commitlint 对于团队协作具有很大的益处,尤其是在大型项目中
commitlint 的工作原理是通过配置文件(如 commitlint.config.js)定义一组提交信息规则。当开发者提交更改时,commitlint 会检查提交信息是否符合这些规则。如果不符合,提交将被拒绝,开发者需要修改提交信息以满足规则要求
安装
在项目中安装commitcli和@commitlint/config-conventional常规的配置:
➜ npm install @commitlint/config-conventional @commitlint/cli -D
配置
根目录下创建.commitlintrc.js
配置文件:
module.exports = {
extends: [], // 继承规则
rules: {}, // 具体规则
prompt: {} // 交互式
}
2
3
4
5
commitlint的配置也包含多种选项,其中常用的就是extends、rules、prompt
extends用来继承第三方规则,通常就是官方提供的规则:
module.exports = {
extends: ["@commitlint/config-conventional"]
}
2
3
rules用来配置具体的规则,或者覆盖继承的规则,常用的规则属性如:type-enum(用来限制提交类型)、type-case(格式大小写)、type-empty(类型是否为空)、subject-empty(主题信息)等:
module.exports = {
rules: {
'type-enum': [ // 定义提交类型
2,
'always',
[
'feat', // 新功能
'bug', // 具体修复的bug
'fix', // 修复的功能
'ci', // ci更新
'docs', // 文档
'chore', // 比较杂的内容
// ...
]
],
'type-case': [2, 'always', 'lower-case'], // 提交类型大小写
'type-empty': [2, 'never'], // 提交类型不能为空
'subject-empty': [2, 'never'], // 提交信息不能为空
// ...
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
提交类型错误,不存在 'happy' 类型:
➜ git:(dev) ✗ echo 'happy: 测试' | npx commitlint
⧗ input: happy: 测试
✖ type must be one of [feat, bug, fix, ui, ci, perfect, docs, style, perf,
release, deploy, refactor, test, chore, revert, merge, build] [type-enum]
✖ found 1 problems, 0 warnings
2
3
4
5
6
提交信息不能为空:
➜ git:(dev) ✗ echo 'feat' | npx commitlint
⧗ input: feat
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
2
3
4
5
6
正确提交:
➜ git:(dev) ✗ echo 'feat: 测试' | npx commitlint
commitizen
commitlint主要在commit时对提交信息进行校验,而commitizen是在commit前通过交互式进行提交,这样就可以统一输入内容,本人认为相对繁琐。下面来看如何使用
安装
安装commitizen
,可以安装在全局也可以安装在项目中,安装方式和工具可自行选择:
➜ yarn add commitizen -D
➜ npx commitizen init cz-conventional-changelog --yarn --dev --exact
2
3
在package.json
中配置脚本:
{
"scripts": {
"commit": "cz"
}
}
2
3
4
5
使用
在项目中先对代码进行暂存,然后进行提交:
➜ npm run commit
当执行以上命令后,就会进入commitizen交互阶段:
➜ git:(main) ✗ npm run commit
$ cz
cz-cli@4.3.0, cz-conventional-changelog@3.3.0
# 选择提交类型
? Select the type of change that you're committing: (Use arrow keys)
❯ feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)
# 这里选择feat
? Select the type of change that you're committing: feat: A new feature
? What is the scope of this change (e.g. component or file name): (press enter to skip) config # 修改范围 scope
? Write a short, imperative tense description of the change (max 86 chars): # 主题 commit简短信息
(5) 初始化项目
? Provide a longer description of the change: (press enter to skip) # 长描述,这里没有
? Are there any breaking changes? No # 是否是不兼容性的改变 否
? Does this change affect any open issues? No # 是否影响相关issue
[main (root-commit) 76f5d72] feat(config): 初始化项目
4 files changed, 1111 insertions(+)
create mode 100644 .gitignore
create mode 100644 .npmrc
create mode 100644 package.json
create mode 100644 yarn.lock
✨ Done in 169.05s.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
这样团队都是用此脚本时commit信息就会被规范化而不会出现五花八门现象
自定义规范
安装cz-customizable
插件进行自定义配置:
➜ yarn add cz-customizable -D
修改commitizen的规则路径:
// package.json
{
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
}
}
2
3
4
5
6
7
8
commitizen默认会读取根项目下的.cz-config.js
文件,新建文件:
module.exports = {
// 自定义提交类型
types: [
{
value: '✨ feat',
name: '✨ feat: 新功能'
},
{
value: '🐛 fix',
name: '🐛 fix: 修复bug'
},
{
value: '🎉 init',
name: '🎉 init: 初始化'
},
{
value: '✏️ 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'
}
],
// 修改范围
scopes: [
{ name: 'components' },
{ name: 'config' },
{ name: 'services' },
{ name: 'utils' },
{ name: 'styles' },
],
// 每个阶段提示信息
messages: {
type: '请选择提交类型(必填):',
customScope: '请选择文件修改范围(可选):',
subject: '请简要描述提交信息(必填):',
body: '请输入详细描述(可选):',
breaking: '列出任何BREAKING CHANGES(可选):\n',
footer: '请输入要关闭的issue,如:#1, #2, #3(可选)\n',
confirmCommit: '确定要提交吗?'
},
allowCustomScopes: true,
allowBreakingChanges: [':sparkles: feat', ':bug: fix'],
subjectLimit: 72
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
接下来看下效果:
➜ git:(main) ✗ yarn commit
$ cz
cz-cli@4.3.0, cz-customizable@7.0.0
All lines except first will be wrapped after 100 characters.
? 请选择提交类型(必填): (Use arrow keys)
❯ ✨ feat: 新功能
🐛 fix: 修复bug
🎉 init: 初始化
✏️ docs: 文档变更
💄 style: 代码的样式美化
♻️ refactor: 重构
⚡️ perf: 性能优化
(Move up and down to reveal more choices)
2
3
4
5
6
7
8
9
10
11
12
13
14
结合commitlint
commitizen可以与commitlint结合使用,commitizen在commit前触发、commitlint主要在commit阶段对提交信息进行校验,那么commitlint可以继承commitizen的规则,从而便可校验通过:
安装commitlint-config-cz
:
➜ yarn add commitlint-config-cz -D
配置commitlint:
// .commitlintrc.js
module.exports = {
// 这里只需要继承cz的规则,也就会读取commitizen的规则
// 上面我们也对commitizen进行了自定义规则,那么commitlint
// 就会读取.cz-config.js的自定义规则进行校验
extends: [/*"@commitlint/config-conventional", */"cz"],
// 其它的归于commitlint的自定义规则全部注释掉
}
2
3
4
5
6
7
8
以上配置好了后,就整合好了那么在提交时就会先触发commitizen然后通过commitlint对commit进行校验
commitizen我更认为比较繁琐,觉得使用commitlint一个结合原生的git提交就足够了
Husky
Husky是一个git钩子,可以在git的commit前和commit时添加自定义校验,通常用来eslint、stylelint和commitlint,看看如何使用
安装配置
➜ yarn add husky -D
➜ npx husky install
2
上面安装后便会在根目录下生成.husky
目录,里面包含了commit的钩子
在package.json
中添加脚本,在项目下载时自动对git生成钩子函数:
{
"scripts": {
"postinstall": "husky install" // 安装完后,生成git hooks
}
}
2
3
4
5
集成lint
在项目开发完后进行提交前一般都会对代码进行lint或者测试,这里就以lint为例,在提交git时对项目代码进行eslint、stylelint检查
首先设置相关的lint脚本:
{
"scripts": {
"lint": "yarn lint:js && yarn lint:style",
"lint:js": "vue-cli-service lint --fix",
"lint:style": "stylelint 'src/**/*.{less,vue,tsx}' --fix"
}
}
2
3
4
5
6
7
添加git hooks,在git提交前对代码进行校验:
➜ npx husky add .husky/pre-commit "yarn lint"
添加完后在.husky/pre-commit
中就会添加一下信息:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn lint
# 这里是手动写入,也就是sh脚本
echo Lint Sucessful
# 若lint fix后将已经暂存的文件继续暂存以commit
git add $(git diff --name-only --cached)
2
3
4
5
6
7
8
9
接下来集成commitlint
集成commitlint
添加以下脚本在commit时启动commitlint检查提交信息:
➜ npx husky add .husky/commit-msg 'npx --no-install commitlint -e'
执行完后会在.husky/commit-msg
中写入以下内容:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install commitlint -e
echo commit success 🎉
2
3
4
5
到这里就已经集成完毕了,以下为集成后的使用效果:
号外 📣
注意使用commitizen需要使用cz
钩子而不能使用git commit
了,其实本人觉得使用commitizen交互性比较繁琐,可以在项目中直接使用commitlint并定义相关规则,然后使用git commit
对触发husky钩子并对commit信息进行验证