详解如何更优雅地管理你的代码提交(commitizen git cz和 conventional-changelog)

本文主要解决以下问题:

  1. 如何使用工具生成符合Angular commit规范的message?
  2. 如何通过gitHoos验证message是否符合规范?
  3. 如何使用工具自动生成changelog?

如果你想了解更详细的过程,请认真往下阅读;如果你想快速查看如何使用,请看『总结』目录。

前言

在一个多人协作的项目中,简洁清晰易懂的代码提交注释是能够快速定位问题的有效方式。commit message应该说明本次提交的目的。

对比下面这两张代码提交commit log图:

第一张:message没有实际的意义,看不出来本次提交改动的范围。

图1.png

第二张:message简洁清晰易懂,可以看出当前是新增功能、修复问题等,并可看出此次提交影响的范围。

图2.png

通过上面两张图可以看出,message写的符合规范是多么的重要!

那我们在日常工作中,仅仅通过人工去输入message,无法完全保证message提交的规范性。

接下来介绍一种社区比较流行的规范Angular 规范,并且通过工具去生成符合这种规范的message信息。

Angular commit规范

介绍

规范格式概览

<type>(<scope>): <subject> #header部分
// 空一行
<body>
// 空一行
<footer> 
复制代码

Header 是必需的,Body 和 Footer 可以省略。

规范格式详解

Header

Header部分只有一行,包括三个字段:type(必需)、scope(可选)和subject(必需)。

type

用于说明本次commit的类型

只允许使用下面7个标识

  • feat:新功能(feature)
  • fix:修补bug
  • docs:文档(documentation)
  • style: 格式(不影响代码运行的变动)
  • refactor:重构(即不是新增功能,也不是修改bug的代码变动)
  • perf: 性能提升(提高性能的代码改动)
  • test:测试
  • build:构建过程或辅助工具的变动(webpack等)
  • ci:更改CI配置文件和脚本
  • chore:不修改src或测试文件的其他更改
  • revert:撤退之前的commit

如果type为feat、fix、perf、revert,则该 commit 将肯定出现在 Change log 之中。其他情况(docs、chore、style、test)由你决定,要不要放入 Change log,建议是不要。

scope

用于说明本次commit影响的范围,比如首页、详情页等。

subject

用于说明本次commit的简短描述,不超过50个字符。

Body

用于本次commit的详细描述,可以分成多行

举例(实际应用应说明具体改动):

more info... 

- first changes...
- second changes...
复制代码

Footer

只用于下面两种情况

不兼容变动

如果当前代码与上一个版本不兼容,则 Footer 部分以BREAKING CHANGE开头,后面是对变动的描述、以及变动理由和迁移方法。

举例:

vue-next changelog.md:github.com/vuejs/vue-n…

BREAKING CHANGE: `getTextMode` compiler option signature has changed from

  ``ts
  (tag: string, ns: string, parent: ElementNode | undefined) => TextModes
  ``

  to

  ``ts
  (node: ElementNode, parent: ElementNode | undefined) => TextModes
  ``
复制代码

关闭Issue

如果当前 commit 针对某个issue,那么可以在 Footer 部分关闭这个 issue 。

Closes #123, #234
复制代码

Revert(可忽视)

还有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以revert:开头,后面跟着被撤销 Commit 的 Header。

revert: feat(pencil): add 'graphiteWidth' option

This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
复制代码

Body部分的格式是固定的,必须写成This reverts commit .,其中的hash是被撤销 commit 的 SHA 标识符。

如果当前 commit 与被撤销的 commit,在同一个发布(release)里面,那么它们都不会出现在 Change log 里面。如果两者在不同的发布,那么当前 commit,会出现在 Change log 的Reverts小标题下面。

Commitizen 生成message工具

Commitizen是一个撰写合格 Commit message 的工具。

全局安装commitizen

npm install -g commitizen
复制代码

项目初始化commitizen

在项目目录里,运行下面的命令,使其支持 Angular 的 Commit message 格式

// 使用npm包cz-conventional-changelog进行初始化
commitizen init cz-conventional-changelog --save --save-exact
复制代码

cz-conventional-changelog介绍

执行完上述命令后,会往package.json文件中的devDependencies中加入cz-conventional-changelog包,并且自动增加config配置项,如下:

"devDependencies": {
    "cz-conventional-changelog": "^3.3.0"
},
"config": {
   "commitizen": {
       "path": "./node_modules/cz-conventional-changelog"
    }
}
复制代码

之后,凡是用到git commit命令,一律改为git cz。这时就会出现选项,用来生成符合格式的commit message。

image.png

我们也可以在package.json文件中的script中配置命令:

"scripts": {
    ...
    "commit": "git cz"
},
复制代码

之后在执行git commit时,直接运行npm run commit即可!

完整版生成message示例

如果想生成Breaking changes,请在Are there any breaking changes?的时候选y

image.png

gitHooks验证message规范性

请戳快速了解Vue如何添加git hooks钩子(pre-commit、commit-msg)

生成changelog

介绍

如果你的所有commit都符合Angular commit规范,那么发布新版本时,就可以通过脚本自动生成changelog。

示例:vue-next v3.1.0 changelog

生成的changelog文档包括以下几个部分:

  • Features(对应type: feat)
  • Bug Fixes(对应type: fix)
  • Code Refactoring (对应type: refactor且breaking changes为y)
  • Performance Improvements(对应type: perf)
  • Reverts (对应type: revert)
  • BREAKING CHANGES (显示body中为BREAKING CHANGES的内容)

每个部分都会罗列相关的 commit ,并且有指向这些 commit 的链接。当然,生成的文档允许手动修改,所以发布前,你还可以添加其他内容。

conventional-changelog

用来生成changelog的工具

conventional-changelog介绍

安装

npm install -g conventional-changelog
复制代码

生成changelog

使用下述命令可生成changelog:

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.jsonscripts字段。

{
  "scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
  }
}
复制代码

以后,直接运行下面的命令即可。

npm run changelog
复制代码

示例

1. commit log如图:
image.png
2. 生成的changelog如图:

image.png

总结

1. 生成message

npm install -g commitizen
// 切换至项目目录
commitizen init cz-conventional-changelog --save --save-exact
// 命令行执行git cz生成commit message
git cz   // 或者package.json配置`scripts`
复制代码

2. 验证message规范性

// 安装lint-staged
npm install lint-staged --save-dev
// package.json
"gitHooks": {
    "pre-commit": "lint-staged",
    "commit-msg": "node build/verify-commit-msg.js"
},
"lint-staged": {
    "*.{js,vue}": [
      "vue-cli-service lint",
      "git add"
    ]
}
// verify-commit-msg.js
const chalk = require("chalk");
const msgPath = process.env.GIT_PARAMS;
const msg = require("fs")
    .readFileSync(msgPath, "utf-8")
    .trim();
const commitRE = /^(build|chore|ci|docs|feat|fix|wip|perf|refactor|revert|style|test|temp|)(\(.+\))?: .{1,50}/;
// 根据正则表达式校验提交的message是否符合团队规范
if (!(commitRE.test(msg) || msg.indexOf("Merge") === 0)) {
    console.error(
        `  ${chalk.bgRed.white(" ERROR ")}
  [${chalk.red(msg)}] 是 ${chalk.red("无效的提交消息格式")}
  ${chalk.red("自动生成更新日志需要正确的提交消息格式 例如:")}

  ${chalk.green("issue-1 feat(模块): 预发布环境增加 A 模块")}
  ${chalk.green("issue-2 fix(文案): 修复错误文案")}`
    );
    // 以非0值退出,放弃提交
    process.exit(1);
}
复制代码

3. 生成changelog

// 安装
npm install -g conventional-changelog
// 生成全部changelog
conventional-changelog -p angular -i CHANGELOG.md -s -r 0
// 生成自上次版本号变更以来changelog
conventional-changelog -p angular -i CHANGELOG.md -s
复制代码

常见问题

1. gitHooks钩子验证时,仅可保留下述方式的其中一种:

  • .git/hoos/目录下,去掉.sample后缀后生效的钩子,如

image.png

  • package.json中通过gitHoos定义的钩子,可自定义通过npm包或者js文件去校验

image.png
2. 每一次版本发布记得修改package.json中的version版本,生成changelog需根据版本号去生成

参考文档

  1. www.jianshu.com/p/c7e40dab5…
  2. www.ruanyifeng.com/blog/2016/0…
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享