自动生成变更日志及规范git提交记录(release-it+husky+ commitizen+ commitlint)

4,138 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

困境

每次写完git commit记录后,还要在不同的地方同步当前项目的进展,是不是感觉很麻烦?因为懒得去写或者在git里面复制粘贴很麻烦,所以要想办法把提交信息归纳到变更记录的文档里面,需要的时候,直接复制粘贴就好了。

在解决如何自动生成变更日志这个问题前,需要先探讨一个问题,就是如何生成规范的git提交信息?

因为在日常提交commit时,各种五花八门的提交信息会导致维护项目时难以为继,并且如果自动生成了日志,也会导致格式不统一,在汇报时也难以做相关类目的统计。

本文介绍的是目前社区提出较为通用的提交规范称为:Conventional Commits。下面就开始实战一下:

本篇文章不会详细介绍规范的内容,如果有兴趣可以自行研究相关细节。

后面会通过自动化插件来生成符合规范的commit,因此笔者认为在本文中你无需了解更多细节增加学习成本,导致概念太多看不下去。

初始化项目

快速创建一个项目并且初始化,方便后面的演示。

# 创建新的目录
mkdir changelog

# 切换到新建目录下
cd changelog

# 初始化npm项目
npm init -y

# 初始化git
git init

安装commitizen

建议不用git commit命令填写git提交信息(因为这样容易出错,并且你有可能会忘记一些规范的要求)。而是通过commitizen来自动生成。

commitizen会询问一些问题,它会根据开发者的回答来生成符合Conventional Commits标准的提交信息。

输入以下命令安装

# 安装commitizen

npm install --save-dev commitizen

# 初始化Conventional Commits规范适配器

npx commitizen init cz-conventional-changelog --save-dev --save-exact

上面介绍的适配器,只是其中一种,社区还提供了很多其它的适配器,你可以去项目页面查看。如果这些都没法满足你┓( ´∀` )┏,你也可以自己写一个。

最后一步,需要在package.json中添加一个script

... // 此处省略其它配置
"scripts": {
    ..., // 此处省略其它配置
    "commit": "cz"
}
... // 此处省略其它配置

此时你的package.json应该是这样的:

{
  "name": "changelog",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "commit": "cz"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "commitizen": "^4.2.4",
    "cz-conventional-changelog": "^3.3.0"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}

创建.gitignore文件,并将node_modules添加到git忽略中

如果是mac或Linux可以运行下面指令完成:

echo "node_modules" > .gitignore

下面我们开始使用commitizen来生自动生成commit

# 添加改动
git add .

# 运行 commitizen
npm run commit

此时你会看到下面的内容:

可选项如下:

  • feat: 新的功能
  • fix: 修复buf
  • docs: 只修改文档
  • style: 不影响代码含义的修改(比如:空格、格式化、添加缺少的分号等)
  • refactor: 重构代码(既不修复错误,也不增加功能)
  • perf: 提高性能
  • test: 添加测试或纠正现有测试
  • build: 影响构建系统或外部依赖的变化(如glup、npm等)
  • ci: ci配置文件和脚本的改变 (如:Travis、Circle)
  • chore: 其它不修改src或测试文件的改动
  • revert: 回滚之前的提交

此处选择feat并回车。

接着需要指定变动的范围(如:某个组件、某个功能、某个文件等,此项可以跳过)

此处填写某个范围并回车

接着需要写一个针对这次提交改动的简短描述

此处填写一个简短的描述并回车

接着需要写一个针对这次提交改动的详细描述(可以跳过) 此处填写一个超长的描述并回车

接着需要确认是否有重大变更,如果有则输入y回车后需要写具体地重大变更内容,如果没有则输入N即可 此处输入y回车后填写有重大变更并回车

接着需要确认是否与某个未关闭的issue有关联,如果有则输入y回车后需要写具体影响的issue,如果没有则输入N即可 此处输入y回车后我们填写完成 #1

此时我们可以看到,一条提交信息就自动生成完毕

通过git log命令查看刚刚生成的内容,此时我们完成了自动化生成提交信息的功能。

image.png

使用husky+commitlint

如果你的小伙伴没有通过commitizen生成提交信息,而是使用了git commit命令,这个时候就需要强制检查提交信息是否符合规范。

接下来将使用+commitlinthusky来进行检查,执行下面的命令

# 安装 commitlint cli 以及 conventional插件
npm install --save-dev @commitlint/config-conventional @commitlint/cli

# 安装 Husky
npm install husky --save-dev

配置commitlint

新建commitlint.config.js文件,并添加下面的内容:

module.exports = {extends: ['@commitlint/config-conventional']};

使用下面的指令,在提交commit前,检查提交信息。

# 激活husky钩子
npx husky install

# 添加husky的commit-msg钩子,在提交前对提交信息进行检查
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

可以在package.json中的scripts.prepare中添加husky install来确保每个使用的人在使用项目前都会激活husky钩子。

下面来测试一下husky是否正常工作。

输入下面的指令,将会新建一个文件,并添加到git后进行提交(如果非mac或Linux,可以自己手动创建文件)

touch new-feature
git add new-feature
git commit -m "这是一个新的改动"

可以看到,husky很好地拦截了不符合规范的提交,并做了提示。

接下来,我们输入一个符合规范的提交

git commit -m "feat: 这是一个新的改动"

你可以看到提交成功了,此时终于把git提交信息规范化搞定了!!接下来就是最重要的自动生成日志环节:

使用release-it自动生成变更日志

在github中,新建一个名为changelog的仓库,并且添加远程端地址:

PS: 你可以在你的git仓库中创建一个

将本地的内容先push到远程端,由于生成项目时,可能会有文件默认生成,因此加上-f参数,强推一下master到远程端

git push --set-upstream origin master -f

接下来我们安装release-it

npm init release-it

一路回车,按照默认配置进行配置。初始化完成后我们需要注意以下几点:

当前不需要在npm进行发布,因此需要在.release-it.json中添加下面的配置,禁用npm发布:

"npm": {
  "publish": false
}

为了兼容当前的提交信息格式,还需要执行下面的指令安装一个插件:

npm install @release-it/conventional-changelog --save-dev

如果想使用angular默认的changelog生成规范,只需要进行下面的配置就可以了:

"plugins": {
  "@release-it/conventional-changelog": {
    "preset": "angular",
    "infile": "CHANGELOG.md",
    "ignoreRecommendedBump": true, // 笔者希望自己选择 bump 的策略,而不是按照推荐的策略,因此将此选项打开
    "strictSemVer": true // 笔者希望发布的版本号必须是 strict-semver 的版本号,因此将此选项打开
  }
}

如果有兴趣,可以查阅插件文档进行更多的配置。

这里要注意一点:默认配置下,只会有featfix的提交会在changelog中显示出来(在文末会介绍如何让其他类型的提交信息也在changelog中展示出来,并且对类型标题做定制)。

插件会自动生成tag,我们需要自定义一下生成tag时的提交信息。在配置项中加入下面的配置,来完成提交信息的自定义:

"git": {
  "commitMessage": "chore(tag): release v${version}"
}

先把之前的改动都提交一下,再执行release操作,指令如下:

git add .
git commit -m "feat: 添加新的功能配置"
npm run release

上图中,release-it询问你下一个版本的版本号,此版本号的选择需要基于semver规范,你可以阅读一下规范文档。或者笔者从一篇博客中找到下面一幅图能很直观地解释区别(图片来源地址)

image.png

在这里选择patch (1.0.1),一路默认回车。

完成后就可以在github中看到release信息

同样你的CHANGELOG.md文件也自动生成了

回顾一下之前提交的内容,你会发现:

  • 所有feat类型的提交都被按照顺序归纳到了Features下方。
  • 所有的重大变更,单独被拎了出来,归纳在BREAKING CHANGES下方。

如果你希望定制这个Features文案该怎么做?而且就像前文说的,目前的changelog只展示featfix,如果希望展示其它的提交,又该怎么做?

定制changelog

我们默认传入的"preset": "angular"相当于下面的配置:

"preset": {
  "name": "conventionalcommits",
  "types": [
    {"type": "feat", "section": "Features"},
    {"type": "fix", "section": "Bug Fixes"},
    {"type": "chore", "hidden": true},
    {"type": "docs", "hidden": true},
    {"type": "style", "hidden": true},
    {"type": "refactor", "hidden": true},
    {"type": "perf", "hidden": true},
    {"type": "test", "hidden": true}
  ]
},

根据官方文档的配置指引

如果现在要让docs类型的标题为📚文档featfix类型更换一下文案。

那么只要在.release-it.json文件中,改动下面的配置即可:

"plugins": {
  "@release-it/conventional-changelog": {
-    "preset": "angular",
    "infile": "CHANGELOG.md",
    "ignoreRecommendedBump": true,
    "strictSemVer": true,
+    "preset": {
+      "name": "conventionalcommits",
+      "types": [
+        {
+          "type": "feat",
+          "section": "✨新功能"
+        },
+        {
+          "type": "fix",
+          "section": "🐛问题修复"
+        },
+        {
+          "type": "docs",
+          "section": "📚文档"
+        }
+      ]
+    }
  }
}

添加一个README.md文档,并且输入以下指令,看一下配置的效果。

git add .
git commit -m "docs: 添加README.md文档"
npm run release

发版成功后,你就能在你的release内看到下面的内容:

添加的docs类型成功显示在📚文档的标题下。同样以此类推,你可以设置你需要显示的提交类型及其相关的标题,让你的CHANGELOG看起来更加符合你的习惯。

如果你不知道用什么emoji来表达你的类型,可以看看这个项目,给你一些启发的灵感:gitmoji.dev/

经过一番操作,终于目标达成,以后同步项目改动只需要把changelog文档丢出来,或者在该文档内复制相关内容就好啦!

本文的示例仓库地址是:github.com/zyc95/chang…