配置 git commit 提交信息约束

10 min read 代码笔记

多人协作开发时,git commit 信息规范尤为重要。仅靠口头约定难以执行,通常需借助工具自动约束提交信息。关于工具的使用,市面上的相关教程多雷同且不够清晰,配置后常常不明所以。本文梳理工具作用和配置流程,供自己和有同样困惑的你参考。

第一步,拦截

实现提交约束,核心是拦截不规范的提交信息,主要依赖两个工具: @commitlint/clihusky。具体作用如下:

  • @commitlint/cli:校验器,检查 commit 信息是否符合既定规则。
  • husky:Git Hooks 工具,可以让你在 Git 事件发生前后,执行一些自定义的脚本。比如我们就需要利用它的钩子 commit-msg,它在输入提交信息后,提交前触发。

在项目中安装这两个工具:

pnpm add -D @commitlint/cli husky

然后执行一下 husky 的初始化:

pnpm exec husky init 

此命令执行后,会做两件事,一是会在 packages.jsonscripts 中添加这条命令:

"scripts": {
  "prepare": "husky"
}

这样别人克隆项目并安装依赖时,会自动注册 git hooks。

第二件事就是会在你的项目中创建 .husky 目录,还会添加一个 .husky/pre-commit 钩子文件,建议删除自动生成的 .husky/pre-commit 文件,避免后续不必要的钩子影响。然后手动添加 commit-msg 钩子,内容如下:

pnpm exec commitlint --edit "$1"

前面说了,这个钩子的执行时机是在 commit 信息输入后,提交前。然后我们让它执行上面这句命令,其实就是检查提交信息的规范,commitlint 命令是 @commitlint/cli 提供的。补充一点,我不建议任何命令式的创建这条命令钩子,可能会因为版本,环境等问题出错,不要偷懒,手动添加一下是最保险的。

然后我们还需要添加一个配置文件 commitlint.config.js,它的作用是配置一些规范,让检查器根据配置的规范来检查拦截,规范配置后续补充,这里先写一个空配置::

export default {
    // 
}

此时,其实你的项目已经具备拦截的能力,不信的话可以尝试 git commit 一下。如果你按照上面配置了,此时你会发现不管你的提交信息是什么内容,husky 都会给你拦截了,日志会如下这样:

   input: feat: 测试提交
   Please add rules to your `commitlint.config.js`
    - Getting started guide: https://commitlint.js.org/guides/getting-started
    - Example config: https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/config-conventional/src/index.ts [empty-rules]

   found 1 problems, 0 warnings
   Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky - commit-msg script failed (code 9)

此时所有格式的提交信息都会被拦截,即使像 feat: 测试提交 这样的你以为规范的格式也不例外。

原因其实是因为我们没有配置 “规范”,我们的 commitlint.config.js 文件是空的,这样校验器也不知道什么样的提交信息才算正确的,所以一股脑都给你拦截住了。那么下一步,我们就要去配置一下“规范”。

第二步,配置规范

现在主流的提交信息规范是 Angular 社区提出的,即在提交信息前加上如 feat:fix:chore: 等前缀,应用该规范即可满足大多数项目需求。而我们也无需手动编写此种规范,社区已经有了预设包,我们只需安装并应用该预设包即可。

安装预设包:

pnpm add -D @commitlint/config-conventional

然后在 commitlint.config.js 文件中应用一下这个预设包:

export default {
  extends: ["@commitlint/config-conventional"],
};

注意,你需要根据项目环境选择配置方式,如果项目使用 CommonJS 规范,则这样写:

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

配置完成后,你的项目就可以按照规范来拦截 commit 了,现在你的提交信息必须要包含前缀,还需要注意前缀后面要加一个英文空格,不然也是不规范的,如:

   input: feat:测试 # 注意这里前缀后面没有空格,所以被拦截了
   subject may not be empty [subject-empty]
   type may not be empty [type-empty]

   found 2 problems, 0 warnings
   Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky - commit-msg script failed (code 1)

具体有哪些前缀,可以去官方文档查看下,这里不多赘述。

到了这里已经实现了“提交约束”这个功能,项目中做到这一步已经够了。但是手动输入 commit 信息还是容易出错,我们需要一个能够自动生成规范化提交信息的工具,提升一下开发体验。

更进一步,自动生成规范化的 message

如标题所述,我们可以用程序自动生成规范化的提交信息。所谓的自动是自动加上合适的前缀,消息本体还是我们自定义的。

我们需要用到两个库:commitizencz-gitcommitizen 是交互式提交信息生成器,需要配合适配器使用。cz-git 是国人开发的一款适配器,界面友好且支持中文,推荐使用。无需深入了解原理,直接将两者作为固定搭配使用即可。

安装这两个插件:

pnpm add -D commitizen cz-git

然后在 packages.json 中做两件事,一是在 script 中添加一条提交命令:

"scripts": {
    "commit": "git-cz"
}

这样我们后面使用 pnpm run commit 来代替 git commit 命令,git-cz 命令是 commitizen 提供的,也就是将 git 提交操作交给这个引擎接管了。然后我们需要设置一下该引擎的适配器路径:

"config": {
    "commitizen": {
        "path": "./node_modules/cz-git"
    }
}

cz-git 作为适配器使用。

此时当你执行 pnpm run commit 后,就会发现终端中出现这样的选择式交互方式:

你可以选择要提交信息的类型,这样会自动给你的 message 加上对应的前缀。

默认界面为英文,可通过在 commitlint.config.js 中配置 cz-git,实现中文交互和自定义选项。具体配置可参考cz-git 配置模板,以下是我的配置:

import { defineConfig } from 'cz-git'

export default defineConfig({
	extends: ['@commitlint/config-conventional'],
	prompt: {
		messages: {
			type: '选择你要提交的类型 :',
			scope: '选择一个提交范围(可选):',
			subject: '填写简短精炼的变更描述 :\n',
			confirmCommit: '是否提交或修改commit ?'
		},
		skipQuestions: ['body', 'breaking', 'footer', 'footerPrefix'],
		types: [
			{ value: 'feat', name: 'feat:     新增功能' },
			{ value: 'fix', name: 'fix:      修复缺陷' },
			{ value: 'docs', name: 'docs:     文档更新' },
			{ value: 'style', name: 'style:    代码格式' },
			{ value: 'refactor', name: 'refactor: 代码重构 ' },
			{ value: 'chore', name: 'chore:    其他修改' },
			{ value: 'perf', name: 'perf:     性能提升 ' },
			{ value: 'test', name: 'test:     测试相关 ' },
			{ value: 'build', name: 'build:    构建相关 ' },
			{ value: 'ci', name: 'ci:       持续集成 ' },
			{ value: 'revert', name: 'revert:   回退代码' }
		],
		scopes: [
			{ name: 'content', description: '内容更新(.md 文件)' },
			{ name: 'code', description: '代码修改(组件、页面、配置)' }
		],
		allowCustomScopes: false,
		allowEmptyScopes: false
	}
})

现在的交互变成了这样:

手动选择提交类型,最后会自动拼接成一段符合规范的提交信息。还可以在这个过程中补充一系列的定制信息,例如修改范围信息等。更多自定义配置可参考官方文档,这里不再赘述。

结尾

以上就是我关于规范 commit 提交信息的配置过程。通过上述配置,项目的提交信息将自动规范化,协作开发更加高效。