Skip to content

视频地址: BV1kV411V7Pn

使用 commitizen 格式化 commit message

在做项目时,每次进行 git commit -m 'xxx' 都会想给提交起一个合适的名字,当次数多了之后,内容也会变的混乱。当某一天系统出错了,看着那么多的提交记录,可能也不清楚应该要回溯到那个版本。

撰写好的 commit message,除了让未来的自己知道自己是在干嘛,也能让团队之间的沟通更加顺利。在提交 Pull Request / Merge Request 时,审核者能更快第知道增加了那些功能。新成员看着以往的 commit message 也能找到项目的脉络,更容易上手。

Commitizen

https://commitizen-tools.github.io/commitizen/

除了提供 commit message 撰写的建议与规范,commitizen 更进一步提供了交互式的界面,让使用者可以轻松生成符合规范的 commit message。

除了采取来自 Angular 社区的Conventional Commits(约定式提交) 外,commitizen 还提供了可定制化的功能,能让每个团队或者项目都可以依照自己的需求,便携相对应的规范。规范了 commit message 后,除了增加可读性外,也让信息可以被解析做其他运用。例如提升版本号、产生更新日志。

安装与设定 Commitizen

安装

poetry add commitizen --group dev

第一次在项目中使用 commitizen 可以使用初始化指令来完成基本的配置

cz init

1、选择配置文件存放的位置。这里直接选 pyproject.toml 了,也可以使用单独的配置。

$ cz init
Welcome to commitizen!

Answer the questions to configure your project.
For further configuration visit:

https://commitizen-tools.github.io/commitizen/config/

? Please choose a supported config file:  (Use arrow keys)
 » pyproject.toml
   .cz.toml
   .cz.json
   cz.json
   .cz.yaml
   cz.yaml

2、选择提交风格。默认的提交风格有三种,如果不满意也可以自己选择 第三方模板 。这里我选择 cz_conventional_commits

? Please choose a cz (commit rule): (default: cz_conventional_commits) (Use arrow keys)
 » cz_conventional_commits
   cz_customize
   cz_jira

3、选择版本的来源。直接使用默认的 poetry 了。

? Choose the source of the version: (Use arrow keys)
   commitizen: Fetch and set version in commitizen config (default)
   cargo: Get and set version from Cargo.toml:project.version field
   composer: Get and set version from composer.json:project.version field
   npm: Get and set version from package.json:project.version field
   pep621: Get and set version from pyproject.toml:project.version field
 » poetry: Get and set version from pyproject.toml:tool.poetry.version field
   scm: Fetch the version from git and does not need to set it back

4、选择版本方案。选择默认

? Choose version scheme:  (Use arrow keys)
   semver
 » pep440

5、输入版本的格式如何,常用的格式有$version(1.0.0) 或v$version(v1.0.0)。回车默认就好了。

? Please enter the correct version format: (default: "$version")

6、使用 bump 指令是自动更新日志,回车默认

? Create changelog automatically on bump Yes

7、在重大变更时保持当前大版本,回车默认

? Keep major version zero (0.x) during breaking changes Yes

8、选择那一种钩子进行提交,回车默认

? What types of pre-commit hook you want to install? (Leave blank if you don't want to install) (Use arrow keys to move, <space> to select, <a> to toggle, <i> to i
nvert)
 » ○ commit-msg
   ○ pre-push

全部设置完了之后,就会在 pyproject.toml 文件中生成一下内容

[tool.commitizen]
name = "cz_conventional_commits"
tag_format = "$version"
version_scheme = "pep440"
version_provider = "poetry"
update_changelog_on_bump = true
major_version_zero = true

使用 Commitizen

注意:使用之前需要 pre-commit 的内容全部通过校验,不然还是不能提交

# 使用 commitizen 做 commit
# (也可以用简短版的 cz)
cz commit

之前选择的是 cz_conventional_commits 这套规则,所以会出现以下内容

$ cz commit
? Select the type of change you are committing (Use arrow keys)
 » fix: A bug fix. Correlates with PATCH in SemVer
   feat: A new feature. Correlates with MINOR in SemVer
   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 or correcting existing tests
   build: Changes that affect the build system or external dependencies (example scopes: pip, docker, npm)
   ci: Changes to our CI configuration files and scripts (example scopes: GitLabCI)

首先是询问做了那一种改动,接着要求输入改动的各项细节,细节内容查看后面的 Commit Message 标准格式

  • Scope:改动范围
  • Subject:简短描述改动内容
  • Body:详细描述这次的改动
  • Is this a BREAKING CHANGE?:是否是一次大改动?
  • Footer:其他参考咨询,通常是将 Issue 的编号放在这个位置

全部回答完之后,通过之后会产生 commit message

强制检查 commit message

刚开始引入 commitizen 时可能会经常忘记使用它来做 commit,这时候就可以结合 pre-commit 一起来使用(2.0.0 版本之后,cz init 会初始化设置好)。

安装提交校验

pre-commit install -t commit-msg

在项目的 .pre-commit-config.yaml 中添加以下内容

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: check-yaml
      - id: end-of-file-fixer
      - id: trailing-whitespace
      - id: check-toml
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: "v3.0.0" # Use the sha / tag you want to point at
    hooks:
      - id: prettier
        exclude: >
          (?x)^(
              .*.yaml|
              package-lock.json|
              yarn.lock|
              ^.+\.min\.(js|css)$
          )$
        stages: [commit]
  - repo: https://github.com/psf/black
    rev: 23.7.0
    hooks:
      - id: black
  - repo: https://github.com/commitizen-tools/commitizen
    rev: 3.5.3
    hooks:
      - id: commitizen
        stages: [commit-msg]

然后再进行提交,就会出现校验

Commit Message 标准格式

Commit Message 标准格式包括三个部分:Header,Body,Footer

<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>

其中,Header 是必需的,Body 和 Footer 可以省略

Header 部分只有一行,包括三个字段:type(必需)、scope(可选)、subject(必需)

type

用于说明类型。可分以下几种类型

操作说明
feat新功能(A new feature)
fix修复 bug (A bug fix)
improvement对当前功能的改进(An improvement to a current feature)
docs仅包含文档的修改(Documentation only changes)
style格式化变动,不影响代码逻辑。比如清除多余空白,删除分号 等
refactor重构,即不是新增功能,也不是修改 bug 的代码变动
perf提高性能的修改(A code change that improves performance)
test添加或修改测试代码 (Adding missing tests or correcting existing tests)
bui1d构建工具或外部依赖包的修改。比如更新依赖包的版本等 ( Changes that affect the bui1d system or externa1 dependencies)
ci持续集成的配置文件或脚本的修改(changes to our cI configuration files and scripts)
chore杂项。其它不修改源代码与测试代码的修改 ( other changes that don't modify src or test files)
revert撤销某次提交 ( Reverts aprevious commit)

scope

用于说明影响的范围,比如数据层、控制层、视图层等等。

subject

主题,简短描述。一行

Body

对 subject 的补充。可以多行。

主要是一些关联 issue 的操作。

自定义校验规则

.cz.toml

toml
[tool.commitizen]
name = "cz_customize"
tag_format = "$version"
version_scheme = "pep440"
version_provider = "poetry"
update_changelog_on_bump = true
major_version_zero = true


[tool.commitizen.customize]
message_template = "{{change_type}}{% if scope %}({{scope}}){% endif %}:{% if subject %} {{subject}}{% endif %} {% if footer %} {{footer}}{% endif %}"
example = "feature: this feature enable customize through config file"
schema = "<type>: <body>"
schema_pattern = "(feature|fix|docs|style|refactor|perf|test|revert|build).*?:(\\s.*)"
bump_pattern = "^(break|new|fix|hotfix)"
bump_map = { "break" = "MAJOR", "new" = "MINOR", "fix" = "PATCH", "hotfix" = "PATCH" }
change_type_order = ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"]
info_path = "cz_customize_info.txt"
info = """
This is customized info
"""
commit_parser = "^(?P<change_type>feature|fix|docs|style|refactor|perf|test|revert|build).*?:\\s(?P<message>.*)?"
changelog_pattern = "^(feature|fix|docs|style|refactor|perf|test|revert|build)?(!)?"
change_type_map = { "feature" = "Feat", "bug fix" = "Fix" }


# 自定义提交指令
[[tool.commitizen.customize.questions]]
type = "list"
name = "change_type"
choices = [
    { value = "feature", name = "feature: 新功能" },
    { value = "fix", name = "fix: 修复 bug" },
    { value = "docs", name = "docs: 文档的修改" },
    { value = "style", name = "style: 格式化变动,不影响代码逻辑" },
    { value = "refactor", name = "refactor: 重构,即不是新增功能,也不是修改 bug 的代码变动" },
    { value = "perf", name = "perf: 性能优化" },
    { value = "test", name = "test: 增加测试" },
    { value = "revert", name = "revert: 回退" },
    { value = "build", name = "build: 打包" },
]
# choices = ["feature", "fix"]  # short version
message = "请选择提交类型:"


# 修改内容的范围
[[tool.commitizen.customize.questions]]
type = "input"
name = "scope"
message = "请输入修改内容的范围(可选):"


# 自己的提交内容
[[tool.commitizen.customize.questions]]
type = "input"
name = "subject"
message = "请输入简要描述(必填):"


# 自己的提交内容
[[tool.commitizen.customize.questions]]
type = "input"
name = "body"
message = "请输入详细描述(可选):"


[[tool.commitizen.customize.questions]]
type = "input"
name = "footer"
message = "请输入需要关闭的 issue(可选):"

参考: