Skip to content

优雅的提交你的 Commit message #12

@liveKang

Description

@liveKang

优雅的提交你的 Commit message

[TOC]

Commit message 是开发的日常操作, 写好 log 不仅有助于他人 review,还可以有效的输出 CHANGELOG,对项目的管理实际至关重要,但是实际工作中却常常被大家忽略。

希望通过本文,能够帮助大家重视和规范 Commit message 的书写。

一、起因

前段时间在做zeus cli的时候,经常浏览 vue-cli 源码,不由被其 Commit message 所吸引,清晰明了,赏心悦目。

于是就了解了一下,目前社区有多种 Commit message 的 书写规范vue-cli 采用的是 Angular 规范,也是目前使用最广的写法,比较合理和系统化,并且有配套的工具。

二、Commit message 格式

每次提交,Commit message 都包括三个部分:Header,Body 和 Footer。

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

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

不管是哪一个部分,任何一行都不得超过72个字符。这是为了避免自动换行影响美观。

2.1 Header

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

(1)type

type用于说明 commit 的类别,只允许使用下面列表中的标识:

  • feat:新功能(feature)
  • fix:修复 bug
  • docs:文档(documentation)
  • style:代码格式(空格,格式,缺少分号等)
  • refeactor:重构(即不是新增功能,也不是修改bug的代码变动)
  • perf:性能优化(performance)
  • test:单元测试、集成测试、测试用例等
  • chore:对构建过程或辅助工具和库(如文档生成)的更改

(2)scope

scope用于说明 commit 影响的范围,比如model、controller、view、route、component、utils等,视项目而定。

(3)subject

subject是 commit 目的的简短描述,不超过50个字符。

  • 以动词开头,使用第一人称现在时,比如 change,而不是 changed 或 changes
  • 第一字母小写
  • 结尾不加句号(.)

2.2 Body

Body 部分时对本次 commit 的详细描述,可以分为多行。下面是一个范例。

More detailed explanatory text, if necessary.  Wrap it to 
about 72 characters or so. 

Further paragraphs come after blank lines.

- Bullet points are okay, too
- Use a hanging indent
  • 以动词开头,使用第一人称现在时,比如 change,而不是 changed 或 changes
  • 应该说明代码变动的动机,以及与以前行为的对比。

2.3 Footer

Footer 部分只用于两种情况。

(1)BREAKING CHANGE(不兼容变动)

如果当前代码与上一个版本不兼容,则 Footer 部分以 BREAKING CHANGE开头,后面是对变动的描述、以及变动理由和迁移的方法。

BREAKING CHANGE: isolate scope bindings definition has changed.

    To migrate the code follow the example below:

    Before:

    scope: {
      myAttr: 'attribute',
    }

    After:

    scope: {
      myAttr: '@',
    }

    The removed `inject` wasn't generaly useful for directives so there should be no code using it.

(2)关闭 Issue

如果当前 commit 针对某个 issue,那么可以在 Footer 部分关闭这个 issue。

Closes #234

也可以一次关闭多个 issue。

Closes #234, #123, #345

2.4 Revert

还有一种特殊情况,如果当前 commit 用于撤销以前的 commit,则必须以revert开头,后面跟着被撤销 Commit 的 Header。

revert: feat(pencil): add 'graphiteWidth' option

This reverts commit 667ecc1654a317a13331b17617d973392f415f02.

Body 部分的格式是固定的,必须写成This reverts commit <hash>.,其中的hash 是被撤销 commit 的 SHA 标识符。

如果当前 commit 与被撤销的 commit,在同一个发布(release)里面,那么它们都不会出现在 Change log 里面。如果两者在不同的发布,那么当前 commit,会出现在 Change log 的Reverts 小标题下面。

三、项目集成

上面的规则对于未接触过的同学还是需要一些时间适应的,git commit 也是可以通过工具生成的。

3.1 Git commit 模版

当 commit message 一行不够时,可以执行git commit,就会跳出文本编辑器,让你写多行。

git commit

而 git commit 模版就会在指令执行后出现。

修改~/.gitconfig~指系统根目录),添加:

[commit]
	template = ~/.gitmessage

新建 ~/.gitmessage内容可以如下:

# head: <type>(<scope>): <subject>
# - type: feat, fix, docs, style, refactor, test, chore
# - scope: can be empty (eg. if the change is a global or difficult to assign to a single component)
# - subject: start with verb (such as 'change'), 50-character line
#
# body: 72-character wrapped. This should answer:
# * Why was this change necessary?
# * How does it address the problem?
# * Are there any side effects?
#
# footer: 
# - Include a link to the ticket, if any.
# - BREAKING CHANGE
#

实际操作:

3.1 使用 Commitizens 代替你的 git commit

通过工具生成 commit message。

commitzen/cz-cli,借助它提供的git cz命令代替git commit命令,询问式的生成符合规范的 commit message。

除此之外,我们还需要为 commitizen 指定一个 Adapter 比如:cz-conventional-changelog(一个符合 Angular 团队规范的 preset),使得 commitizen 按照我们指定的规范帮助我们生成 commit message。

(1)全局安装

npm install -g commitizen cz-conventional-changelog
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

在全局模式下,新增~/.csrc配置文件,为 commitzens 指定 Adapter。

(2)项目安装

npm install -D commitizen cz-conventional-changelog

package.json 中配置:

"script": {
    ...,
    "ct": "git add . && git-cz",
},
 "config": {
    "commitizen": {
      "path": "node_modules/cz-conventional-changelog"
    }
  }

如果全局安装过 commitizen,那么在对应的项目中执行git cznpm run ct都可以。

项目局部安装,无法使用git cz,可以使用npm run ct,建议全局安装。

效果如下:

(3)自定义 Adapter

也许 Angular 的那套规范我们不习惯, 那么可以通过指定 Adapter cz-customizable 指定一套符合自己团队的规范。

# 全局安装
npm i -g cz-customizable

# 项目安装
npm i -D cz-customizable

修改 ~/.czrc 或 package.json 中的 config 为:

// ~/.czrc
{ "path": "cz-customizable" }

// package.json 中 config
"config": {
	"commitizen": {
	 	"path": "node_modules/cz-customizable"
	}
}

同时在~/ 或项目目录下创建 .cz-config.js 文件, 维护自定义格式。

3.2 Commitlint 校验你的 message

上面是通过工具生成 commit message,当然我们还是可以通过:

# git commit -m "type(scope): subject"
git commit -m "docs(readme): 修改readme"

这种方式直接提交。commitlint,可以辅助 lint commit message,如果提交的 message 不符合指向的规范,则不能提交代码。

安装:

npm i -D @commitlint/config-conventional @commitlint/cli

同时需要在项目目录下创建配置文件.commitlintrc.js,写入:

module.exports = {
	extends: ['@commitlint/config-conventional'],
	// rules 中的内容可自定义,当前与 @commitlint/config-conventional 一致
	// 用于查看可自定义项
	rules: {
		// body 以空行开头
		'body-leading-blank': [1, 'always'],
		// footer 以空行开头
		'footer-leading-blank': [1, 'always'],
		// header 最大长度 72 个字符
		'header-max-length': [2, 'always', 72],
		// 提交影响范围
		'scope-case': [1, 'always', 'lower-case'],
		// 提交内容
		'subject-case': [2, 'always', 'lower-case'],
		// 提交内容不能为空
		'subject-empty': [2, 'never'],
		// 提交内容不能以 . 结尾
		'subject-full-stop': [2, 'never', '.'],
		// 提交类型案例
		'type-case': [2, 'always', 'lower-case'],
		// 提交类型不能为空
		'type-empty': [2, 'never'],
		// 支持的提交类型
		'type-enum': [
			2,
			'always',
			[
				'build',
				'chore',
				'ci',
				'docs',
				'feat',
				'fix',
				'perf',
				'refactor',
				'revert',
				'style',
				'test'
			]
		]
	}
}

(1)针对自定义 Adapter 进行 Lint

如果使用自定义的commitizen adapter,那么你需要:

npm i -D commitlint-config-cz @commitlint/cli

.commitlintrc.js 中写入:

module.exports = {
	extends: [
   		'cz'
 	],
 	rules: {
 	}
}

3.3 Husky 集成

校验 commit message 的最佳方式是结合git hook,目前大前端主要有两种 git 钩子插件 husky(jQuery,babel,create-react-app,Next.js等在用) 和 pre-commit(antd等在用)。

这里推荐Husky的原因:

  • pre-commit 没有 husky 全面,可以大致理解为 pre-commit 是 husky 子集。
  • pre-commit 在集成的过程中,替换了 git commit 的默认行为,使得整套工作流需要处理较多兼容问题,处理麻烦。
  • 官方推荐集成 husky。
npm i husky -D

package.json 中添加

"husky": {
	"hooks": {
		...
		"pre-commit": "npm run lint", // commmit 前执行代码检查
		"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
	}
}

效果如下:

3.4 Standard-version:自动生成 CHANGELOG

通过以上工具的帮助, 我们的工程 commit message 应该是符合 Angular 团队那套, 这样也便于我们借助 standard-version 这样的工具, 自动生成 CHANGELOG。

安装使用:

npm i -D standard-version

package.json 配置:

"scirpt": {
    ...,
    "release": "standard-version"
}

standard-version 有许多其他的特性,详情请看官网介绍。

效果如下:

会在项目根目录下生成一个CHANGELOG.md的文件,如下所示:

以上图片为测试数据。

建议将featfix,以及BREAKING CHANGE放在 changelog 中。其他情况(docschorestylerefactortest),具体视项目而定,建议不要。

四、最后

这样一个符合规范的 commit message,就好像一封邮件。关于 commit message 每个团队和个人都有自己的想法,个人认为:好的习惯,受益终身。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions