22 - Commitizen - 产生合法的 Commit 讯息

针对 commit 讯息的规范,最为人熟知的是 Angular 的 Commit Message Format ,此规则将讯息分为 headerbodyfooter 三个部分,分别又有不同的规则,这使得要写出符合规范的讯息变成了一件不简单的事情。

写个好的 Commit 讯息 - Commitizen

为了避免写出不符规范的 commit 讯息而遭到退回, Commitizen 使用问答的方式,让使用者在完成问答时就可以边写出符合规范的讯息,以减少来回的次数。

Commitizen 是个指令式的工具,藉由 npm 安装,使用 Commitizen 来 commit 程序时会启动使用者所设定的 adapter ,使用 adapter 提供的问题一一询问开发者,每个问题都会确认一部分的 commit 讯息,到最後将所有的回答组合起来,变成一个完整并符合规范的 commit 讯息。

安装 Commitizen

要使用 Commitizen 前,请先安装:

npm install commitizen --save-dev

使用 Commitizen

安装完成後,将 Commitizen 的指令 cz 加入 package.jsonscripts

{
  "scripts": {
    "commit": "cz"
  }
}

这时如果执行指令的话,由於没有设定 adapter ,所以会以预设的 git commit 执行。

加入 cz-conventional-changelog adapter 来执行 Commitizen :

npm install cz-conventional-changelog --save-dev

接着要配置 Commitizen 的 adapter 设定:

{
  "config": {
    "commitizen": {
      "path": "cz-conventional-changelog"
    }
  }
}

config.commitizen.path 的路径会被 require.resolve 解析,因此可以直接写模组名称,它可以被对应至 node_modules 下的真正路径。

执行 npm run commit 後就可以看到终端跳出问题供使用者依照情境做选择:

> cz

? 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) test
? Write a short, imperative tense description of the change (max 88 chars):
 (11) add gitkeep
? Provide a longer description of the change: (press enter to skip)
 I added .gitkeep for folder examples
? Are there any breaking changes? No
? Does this change affect any open issues? No

全部都回答完成後, Commitizen 就会将程序用这个 commit 讯息提交,经由 git log 可以看到建立的讯息:

    feat(test): add gitkeep

    I added .gitkeep for folder examples

整合 Commitlint 与 Commitizen

Commitlint 和 Commitizen 的配置不一致(以 package.json 中的配置为例, Commitlint 的配置属性为 commitlint ,而 Commitizen 的属性为 config.commitizen ),可能导致使用 Commitizen 建立的讯息,不能通过 Commitlint 的检查。

要解决这个问题,我们需要调整设定,让这两个工具使用同一个配置

方法一: @commitlint/prompt

@commitlint/prompt 是个 Commitizen 的 adapter ,它可以让 Commitizen 使用 Commitlint 的配置。

首先安装 @commitlint/prompt

npm install @commitlint/prompt --save-dev

然後修改 package.json 中 Commitizen 的 adapter 路径:

{
  "config": {
    "commitizen": {
      "path": "@commitlint/prompt"
    }
  }
}

如果有安装 adapter cz-conventional-changelog ,请将它解安装。

这样一来执行 npm run commit 的时候, Commitizen 就会使用 Commitlint 的配置作为提示的依据。

方法二: @commitlint/prompt-cli

@commitlint/prompt-cli 是个独立的讯息提示工具,它并不依赖於 Commitizen (虽然使用者不用操作 Commitizen ,但是 @commitlint/prompt-cli 使用了 @commitlint/prompt 实作,因此内部依然与 Commitizen 相依。),并使用 Commitlint 的配置作为设定。

首先安装 @commitlint/prompt-cli

npm install @commitlint/prompt-cli --save-dev

然後 修改 package.json 中的 commit script :

{
  "scripts": {
    "commit": "commit"
  },
}

由於已经不相依於 Commitizen ,可以删除 package.json 中的 config.commitizen 设定与解安装 commitizencz-conventional-changelog 两个套件。
这样一来执行 npm run commit 的时候,就会执行 @commitlint/prompt-cli 提示使用者输入正确的讯息。

方法三: @commitlint/cz-commitlint

前两个方法都采用输入的方式建立讯息,其互动的方式与原本使用 Commitizen 的 cz-conventional-changelog 时有差别。

如果想要使用原本 cz-conventional-changelog 的互动方式,可以使用 @commitlint/cz-commitlint 作为 Commitizen 的 adapter ,它不仅可以使用 Commitlint 的配置,还有与 cz-conventional-changelog 相同的互动方式。

首先安装 @commitlint/cz-commitlint

npm install @commitlint/cz-commitlint --save-dev

然後修改 package.json 中 Commitizen 的 adapter 路径:

{
  "config": {
    "commitizen": {
      "path": "@commitlint/cz-commitlint"
    }
  }
}

如果有安装 adapter cz-conventional-changelog ,请将它解安装。

这样一来执行 npm run commit 时,就可以使用 cz-conventional-changelog 的互动方式与 Commitlint 的配置档做设定了。

最终采用 @commitlint/cz-commitlint 整合 commitlint 与 Commitizen

我们采用方法三的 @commitlint/cz-commitlint 作为整合方案,因为 @commitlint/cz-commitlint 的互动方式较 @commitlint/prompt@commitlint/prompt-cli 更为人性化,也更为易用。

使用 Husky 为 Commitizen 注册 Git hooks

到目前为止,我们都必须自己去叫用 Commitizen 才能启动,使用起来的步骤较原本多,也更不直觉,容易被忽略。

接下来我们藉由 husky 的帮助,将 Commitizen 融入 Git flow 中,让其更加的易用。

使用 husky add 将指令加入 Git hooks :

npx husky add .husky/prepare-commit-msg 'exec < /dev/tty && node_modules/.bin/cz --hook || true'

由於我们已经将 Commitizen 加入 Git hooks 中了,因此可以删除 package.json 中的 commit script :

{
  "scripts": {
    // "commit": "cz"
  }
}

修改完後,要重新注册 Git hooks :

npm install

npm install 会触发在执行 husky-init 时建立的 prepare script ,去做相关的初始化工作。

如果需要 Husky 相关的使用说明,请看本系列的「 20 - Husky - Git Hooks 工具」 一文的介绍。

完成设定後,当你输入指令 git commit ,就会启动 Commitizen 来编辑讯息。

本文重点整理

  • commit 讯息规范复杂,为了避免不符规范的 commit 遭退回, Commitizen 使用交互问答的方式,让使用者在回答问题的过程中迅速且精准的完成讯息的编辑,以避免错误发生。
  • 在整合 Commitizen 与 Commitlint 时,使用 @commitlint/cz-commitlint 作为 Commitizen 的 adapter ,让我们可以用 Commitlint 的配置设定 Commitizen ,并采用 cz-conventional-changelog 的互动方式建立讯息。
  • 与 Husky 整合,可以让我们在编辑 Commit 讯息时,可以启动 Commitizen 。

参考资料


<<:  企划实现(23)

>>:  [Day - 23] - Spring Reactor之进入忍者龟的Flux

Vue.js 从零开始:Vue CLI / Gihub Pages

本篇为Vue CLI最後一篇,专案已经建立好,环境也有概略的说明,接下来当然是上传到Gihub Pa...

R语言-5-套件 & 解题去

看起来很废话但是很实际 使用套件前,要先安装套件 安装完成之後要使用套件要先载入套件 library...

Day 15:Remove Duplicates from linked list

这题开始之前先来介绍一下Linked list(连结串列)的资料结构。 Linked list(连结...

Vue.js指令介绍&基本指令(Directives)(DAY26)

What is Vue Directives? 指令的功能通常用在JavaScript表达式的值改变...

爬虫怎麽爬 从零开始的爬虫自学 DAY12 python列表进阶篇

前言 各位早安,书接上回我们练习了一些基础list用法跟一些技巧,今天我们要来深入探讨list更多能...