Skip to content

Commitizen 快速上手

提示

本文实际是Commitizen+cz-conventional-changelog+husky+commitlint+standard-version的快速上手,因为标题名写太长不好看,所以就省略一下

1.Commitizen+cz-conventional-changelog

1.1 什么是 Commitizen

一个工具,用于规范代码提交信息的工具。cz-conventional-changelog是一个Commitizen的适配器,用于适配conventional-changelog的提交规范。

1.2 如何使用 Commitizen

安装:

这里可以安装到全局,也可以安装到项目中,这里推荐安装到项目中,因为这样可以避免不同项目使用不同的Commitizen版本,导致提交信息不一致的问题。

提交模板有两种选择

官方模板:cz-conventional-changelog, 特点是免配置,开箱即用,但提示全部为英文,不太友好

自定义模板:cz-customizable, 特点是可以自定义添加 emoji 表情,可以自定义提示语言,但需要配置,且无法自定义提交类型(scope)

linpengteng:cz-message-helper修改版,特点是可以自定义 emoji 表情,可以自定义提示语言,可以自定义提交类型(scope),但需要配置

不推荐使用

第一种方式: 使用官方模板cz-conventional-changelog

bash
pnpm add -D commitizen cz-conventional-changelog

需要在项目的根目录下创建一个名为.czrc的文件,文件内容如下:

bash
{
  "path": "cz-conventional-changelog"
}

package.json文件中,补充以下信息:

json
  "scripts": {
    "commit": "git-cz"
    // ...
  },

把代码文件添加到暂存区后,使用 Commitizen 生成符合规范的代码提交信息:

bash
git add . && git status
 pnpm commit

> comm@1.0.0 commit /Users/bddxg/Documents/coding/tmp/版本提交规范
> git-cz

cz-cli@4.3.0, cz-conventional-changelog@3.3.0

? Select the type of change that you're committing:
  feat:     A new feature
  fix:      A bug fix
  docs:     Documentation only changes
❯ style:    Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  refactor: A code change that neither fixes a bug nor adds a feature
  perf:     A code change that improves performance
  test:     Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)

第二种: 使用自定义模板cz-customizable

bash
pnpm add -D commitizen cz-customizable

需要在项目的根目录下创建一个名为.czrc的文件,文件内容如下:

bash
{
  "path": "node_modules/cz-customizable",
}

需要在项目根目录下创建一个名为.cz-config.js的文件,文件内容如下:

js
// .cz-config.js
module.exports = {
  types: [
    {
      value: ':sparkles: feat',
      name: '✨ feat:         新功能',
    },
    {
      value: ':bug: fix',
      name: '🐛 fix:          修复',
    },
    {
      value: ':memo: docs',
      name: '📝 docs:         文档变更',
    },
    {
      value: ':lipstick: style',
      name: '💄 style:        代码格式 (不影响代码运行的变动)',
    },
    {
      value: ':recycle: refactor',
      name: '♻️  refactor:     重构 (既不增加 feature, 也不修复 bug)',
    },
    {
      value: ':zap: perf',
      name: '⚡️ perf:         性能优化',
    },
    {
      value: ':white_check_mark: test',
      name: '✅ test:         增加测试',
    },
    {
      value: ':wrench: chore',
      name: '🔧 chore:        构建过程或辅助工具的变动',
    },
    {
      value: ':rewind: revert',
      name: '⏪ revert:       回退',
    },
    {
      value: ':package: build',
      name: '📦 build:        打包',
    },
  ],
  messages: {
    type: '请选择提交的类型: ',
    scope: '请选择此更改的范围(可选): ',
    customScope: '请输入修改的范围(可选): ',
    subject: '请简要描述提交(必填): ',
    body: '请输入详细描述(可选): ',
    breaking: '列举破坏性修改(可选): ',
    footer: '请输入要关闭的 issue(可选): ',
    confirmCommit: '确认要使用以上信息提交?(y/n): ',
  },
  // 你可以在这里预定义 Scope
  scopes: [],
  allowCustomScopes: true, // 允许输入自定义 Scope 信息
  allowBreakingChanges: [':sparkles: feat', ':bug: fix'], // 允许添加 Breaking Change 的操作
  subjectLimit: 100, // body 主题字数限制
}

把代码文件添加到暂存区后,使用 Commitizen 生成符合规范的代码提交信息:

bash
All lines except first will be wrapped after 100 characters.
? 请选择提交的类型: (Use arrow keys)
 feat:        新功能
  🐛 fix:         修复
  📝 docs:        文档变更
  💄 style:       代码格式 (不影响代码运行的变动)
  ♻️  refactor:    重构 (既不增加 feature, 也不修复 bug)
  ⚡️ perf:         性能优化
 test:        增加测试
(Move up and down to reveal more choices)

这样看起来是不是舒服多了? 但令人遗憾的是,cz-customizable无法自定义提交类型(scope),所以我找到了linpengtengcz-message-helper进行了修改,使其可以自定义提交类型(scope)

第三种方式: 使用linpengtengcz-message-helper

bash
pnpm add -D commitizen cz-message-helper

需要在项目的根目录下创建一个名为.czrc的文件,文件内容如下:

bash
{
  "path": "node_modules/cz-message-helper"
}

package.json文件中,补充以下信息:

json
  "scripts": {
    "commit": "git-cz"
    // ...
  },

需要在项目根目录下创建一个名为.cz-message.js的文件,文件内容如下:

展开查阅详情
js
module.exports = {
  questions: [
    {
      type: 'list',
      name: 'type',
      message: '请选择要提交的更改类型:',
      choices: [
        { value: ':bug: fix: ', name: '🐛 fix: -------- 修复BUG' },
        { value: ':sparkles: feat: ', name: '✨ feat: ------- 新功能' },
        { value: ':memo: docs: ', name: '📝 docs: ------- 仅文档更改' },
        { value: ':lipstick: style: ', name: '💄 style: ------ 不影响代码运行的更改(调整空白、格式、缺少分号等)' },
        { value: ':card_file_box: chore: ', name: '🗃️  chore: ------ 非 src 和 test 的修改' },
        { value: ':recycle: refactor: ', name: '♻️  refactor: --- 重构架构或代码' },
        { value: ':zap: perf:', name: '⚡️ perf:  ------ 改进性能的代码更改' },
        { value: ':test_tube: test: ', name: '🧪 test:  ------ 添加测试单元' },
        { value: ':rewind: revert: ', name: '⏪ revert: ----- 回退至某一个版本' },
        { value: ':truck: merge: ', name: '🚚 merge: ------ 合并一个分支, 解决冲突分支' },
        { value: ':construction_worker: ci: ', name: '👷 ci: --------- 自动化流程配置或脚本修改' },
        { value: ':wrench: build: ', name: '🔧 build: ------ 修改构建流程或外部依赖' },
      ],
    },

    {
      type: 'list',
      name: 'scope',
      message: '请选择更改的范围:',
      choices() {
        return [
          { name: '', value: false },
          { name: '自定义', value: 'custom' },
        ]
      },
      filter(value, answers) {
        return value || ''
      },
    },

    {
      type: 'input',
      name: 'customScope',
      message: '请输入自定义的变更的范围(可选):',
      when(answers) {
        return answers.scope === 'custom'
      },
      filter(value, answers) {
        answers.scope = value || ''
        return value || ''
      },
    },

    {
      type: 'input',
      name: 'subject',
      message: '请简明扼要的摘要描述(建议字数在50字内):',
      validate(value) {
        return value.length > 50 ? `[subject] Exceed limit: 50` : true
      },
    },

    {
      type: 'input',
      name: 'body',
      message: '请提供更详细的变更说明(可选), 使用“\\n”换行:',
    },

    {
      type: 'input',
      name: 'breaking',
      message: '请列出任何重大变化(可选):',
      when(answers) {
        return /^(:[a-z0-9A-Z_-]+(:)(\s*))?(feat|fix)(\2\s*)?$/.test(answers.type.toLowerCase())
      },
    },

    {
      type: 'input',
      name: 'footer',
      message: '请列出此更改关闭的任何问题(可选), 例如: #31,#34:',
    },
  ],

  templater: (answers, wrap) => {
    let template = ''

    template += answers.type ? `${answers.type}` : ``
    template += answers.scope ? `(${answers.scope})` : ``
    template += answers.subject ? `: ${answers.subject}` : ``
    template += answers.body ? `\n\n${wrap(answers.body)}` : ``
    template += answers.breaking ? `\n\nBREAKING CHANGE: ${wrap(answers.breaking)}` : ``
    template += answers.footer ? `\n\nISSUES CLOSED: ${wrap(answers.footer)}` : ``

    return template
  },

  language: 'cn',
}

把代码文件添加到暂存区后,使用 Commitizen 生成符合规范的代码提交信息:

展开查阅详情
bash
版本提交规范 on master [⇡»+] is 📦 1.0.0 via ⬢ v18.16.0
 pm commit

> comm@1.0.0 commit /Users/bddxg/Documents/coding/tmp/版本提交规范
> git-cz

cz-cli@4.3.0, cz-message-helper@1.2.2

? 请选择要提交的更改类型:
  🧪 test:  ------ 添加测试单元
 revert: ----- 回退至某一个版本
  🚚 merge: ------ 合并一个分支, 解决冲突分支
 🐛 fix: -------- 修复BUG
 feat: ------- 新功能
  📝 docs: ------- 仅文档更改
  💄 style: ------ 不影响代码运行的更改(调整空白、格式、缺少分号等)
(Move up and down to reveal more choices)

? 请选择要提交的更改类型: ✨ feat: ------- 新功能
? 请选择更改的范围: 自定义
? 请输入自定义的变更的范围(可选): main.js
? 请简明扼要的摘要描述(建议字数在50字内): 新建了main.js
? 请提供更详细的变更说明(可选), 使用“\n”换行: 初始化项目
? 请列出此更改关闭的任何问题(可选), 例如: #31,#34:

###--------------------------------------------------------###
:sparkles: feat: (main.js): 初始化项目

新建了main.js文件
###--------------------------------------------------------###

? 您确定要继续执行上面的提交吗? (Yneh)

选择 y 进行提交,至此,我们的代码提交信息就符合规范了.

2. husky+commitlint

2.1 什么是 husky+commitlint

husky 是一个 Git 钩子(hook)工具,它能够在 Git 版本控制的不同阶段触发自定义的脚本。

commitlint 是一个用来检查提交信息是否符合规范的工具,它可以在提交前或者提交后对提交信息进行校验,如果不符合规范,就会给出提示或者拒绝提交。

2.2 如何使用 husky+commitlint

bash
pnpm add -D husky commitlint

# 初始化hysky并添加commit-msg钩子
npx husky-init && npx husky add .husky/commit-msg  'npx --no -- commitlint --edit ${1}'

这将在你的项目中初始化 husky,它会创建一个 .husky 文件夹,并在其中添加一些初始配置文件。

与此同时,会自动在 package.json 的 scripts 添加一条命令:

json
"scripts": {
    "prepare": "husky install"
  }

因为我们在提交前添加了 emoji 表情包,所以需要额外的校验规则包

bash
pnpm add -D commitlint-config-gitmoji

手动创建 .commitlintrc.js或者.commitlintrc或者commitlint.config.js 文件,添加以下配置项:

JavaScript
module.exports = {
  extends: ['gitmoji'],
};

测试提交不符合规范的内容,看 commitlint 的校验规则和 husyk 的拦截是否生效

bash
版本提交规范 on master [⇡✘»+?] is 📦 1.0.0 via ⬢ v18.16.0
 git commit -m "haha"
   input: haha
   Your commit should start with gitmoji code. Please check the emoji code on https://gitmoji.dev/. [start-with-gitmoji]
   subject may not be empty [subject-empty]
   type may not be empty [type-empty]

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

husky - commit-msg hook exited with code 1 (error)

3. Contenonal Changelog

3.1 什么是 Contenonal Changelog

conventional-changelog 是一款可以根据项目的 commit 和 metadata 信息自动生成 changelogs 和 release notes 的系列工具。

bash
pnpm add -D conventional-changelog-gitmoji-config

想生成之前所有 commit 信息产生的 changelog 则需要使用这条命令:

bash
npx conventional-changelog -p gitmoji-config -i CHANGELOG.md -s -r 0

其中 -r 表示生成 changelog 所需要使用的 release 版本数量,默认为 1,全部则是 0。

如果你的提交信息已经是规范的,那么可以使用这样的命令来生成 changelog

bash
npx conventional-changelog -p gitmoji-config -i CHANGELOG.md -s

当然这样的命令有点长且啰嗦,可以通过在 package.json 中添加 scripts 来简化命令,具体就不再赘述 令人遗憾的是,我目前的提交都不符合提交约束的规范,只好借被人的图演示一下,从本篇博客开始,我的提交将会遵守提交约束的规范