公司关于代码提交流程一直都很规范,大家一直都遵守规则,平时也没过多关注这方面的细节,直到前一阵子使用的 custom-config 失效了,需要自行处理 changelog,这才注意到协同开发中不仅仅要有代码规范,git commit同样很重要,所以写一篇文章记录下。
1. Commit 规范
关于 commit 规范,业内实践有很多,我们这次主要讨论 angular 方案。而自动生成 commit 方法有很多,这里介绍两种,一种是 git commit.template 提供提交模板,一种是通过 commitizen 这类工具自动生成。
1.1 Commit Template
这种方式比较简单,就是提供一份模板,然后通过 git config commit.template <模板文件>
设置 commit
模板,这样每次执行 git commit
后,默认的 commit message
就会显示成设置的模板。
1.2 Commitizen
先安装 commitizen
npm i commitizen
安装完成后进行初始化
npx commitizen init cz-conventional-changelog --save-dev --save-exact
需要进行 commit 提交时,则执行如下命令,当然也可以写入 npm scripts:
npx cz
通过以上方式,可以实现提交内容格式保持一致。
2. Commit 检查
对于 commit
的校验,方式比较多,这里介绍使用 commitlint
进行 commit
检查。
npm install --save-dev @commitlint/{cli,config-conventional}
echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
需要进行 commit 检查时,则执行如下命令:
git log -1 --pretty=format:%s | npx commitlint
对于 commit 的检查,我们一般通过 gitlab hooks 在提交 mr 时做检查。
3. CHANGELOG
我们在多人协同开发的时候,会遇到打包发布版本时,需要收集更新了什么内容、修复了什么 bug,但是如果我们每次都是手动收集,那么在合入 changelog 的时候就很容易出现遗漏,所以我们需要能自动生成 changelog 的方法,这里我们介绍 conventional-changelog。
npm i conventional-changelog-cli
在需要生成 changelog 的时候,可以执行下面命令:
npx conventional-changelog -p angular -i CHANGELOG.md -s
上面使用的 commit 标准虽然是 angular,但是通过 -p 参数,你也可以按你项目的实际 commit 标准选择 preset。
同时,如果你生成 commit 的标准不在支持范围之内,又或者对生成内容不太满意,还可以通过 changelog.config.js 实现自定义:
module.exports = {
// 使用的提交消息模板
parserOpts: {
headerPattern: /^\[(\w+)(-\w+)?\]\s(.+)$/,
headerCorrespondence: ['type', '_scope', 'subject'],
},
writerOpts: {
transform: (commit) => {
commit = { ...commit };
// 更改type
if (commit.type === 'feature') {
commit.type = '✨ Features | 新特性';
} else if (commit.type === 'bugfix') {
commit.type = '🐛 Bug Fixes | Bug 修复';
} else if (commit.type === 'enhance') {
commit.type = '⚡ Performance Improvements | 性能优化';
} else if (commit.type === 'revert' || commit.revert) {
commit.type = '⏪ Reverts | 回退';
} else if (commit.type === 'docs') {
commit.type = '📝 Documentation | 文档';
} else if (commit.type === 'style') {
commit.type = '💄 Styles | 风格';
} else if (commit.type === 'refactor') {
commit.type = '♻ Code Refactoring | 代码重构';
} else if (commit.type === 'test') {
commit.type = '✅ Tests | 测试';
} else if (commit.type === 'build') {
commit.type = '👷 Build System | 构建';
} else if (commit.type === 'ci') {
commit.type = '🔧 Continuous Integration | CI 配置';
} else if (commit.type === 'chore') {
commit.type = '🎫 Chores | 其他更新';
}
// 短hash
if (typeof commit.hash === 'string') {
commit.shortHash = commit.hash.substring(0, 8);
}
return commit;
},
commitsSort: (commit1, commit2) => {
const time1 = commit1.committerDate;
const time2 = commit2.committerDate;
if (time1 < time2) {
return 1;
} else if (time1 > time2) {
return -1;
}
return 0;
},
},
};
其中的 parserOpts 和 writerOpts 可以参考:
- https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-commits-parser
- https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-writer