Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优雅的提交你的 Commit message #12

Open
liveKang opened this issue May 22, 2019 · 0 comments
Open

优雅的提交你的 Commit message #12

liveKang opened this issue May 22, 2019 · 0 comments

Comments

@liveKang
Copy link
Owner

liveKang commented May 22, 2019

优雅的提交你的 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 每个团队和个人都有自己的想法,个人认为:好的习惯,受益终身。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant