commit规范+commitlint+CHANGELOG自动生成一条龙服务

9,212 阅读17分钟

前言

最近心血来潮打算用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了。啦啦啦🎈🎈🎈

终于结束啦!感谢大家听我啰嗦了这么久,希望可以帮到大家,如果文章中有错漏之处还望指正。谢谢大家啦!!!😜

参考文献

Angular官方comit规范说明

百度到的素不相识空谷先生的语雀文章

优雅的提交你的 Git Commit Message

朋友的博客

以及文中各个工具的文档和源码,就不一一罗列了