规范化git commit信息

冯宇Ops关注

42019.04.25 19:34:17字数 3,385阅读 1,876

原文链接

前言

在git的使用中,一种最佳实践是使用格式化的commit信息,这样方便自动化工具进行处理,可以快速生成Release Notes,甚至可以直接对接CI工具进行更进一步的规范化发布流程。那么如何规范化git commit信息呢?本文将重点讨论这个。

一个最基本的git commit最佳实践

Git-Commit-Best-Practices这个项目总结了一个最基本的git commit实践:

  • Commit Related Changes
  • Commit Often
  • Don't Commit Half-Done Work
  • Test Your Code Before You Commit
  • Write Good Commit Messages
  • Use Branches
  • Agree on A Workflow

而针对其中的Formatting Rules部分,我们将详细讲解下Angular的git commit规范格式。

Angular项目的git commit规范

首先我们先了解一下Angular项目如何规范化自己的commit信息的吧。

Angular项目可以说是业界最广为流传的git commit最佳实践的项目。Angular的贡献要求必须git commit符合自己定义的模板。先来看看Angular的commit记录长什么样子吧: https://github.com/angular/angular/commits/master

image.png

这样的话Angular项目组可以很方便的生成Release Notes

image.png

Angular的git commit实践

完整的Angular的commit教程参见的CONTRIBUTING: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-guidelines

Angular定义的commit基本格式如下:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

除了第一行的Header部分必填外,其余均可选。注意Header, Body, Footer中间有空白行分割。

image.png

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

type用于说明 commit 的类别,只允许使用下面7个标识:

  • feat:新功能(feature)
  • fix:修补bug
  • docs:文档(documentation)
  • style: 格式(不影响代码运行的变动)
  • refactor:重构(即不是新增功能,也不是修改bug的代码变动)
  • test:增加测试
  • chore:构建过程或辅助工具的变动

通常featfix会被放入changelog中,其他(docschorestylerefactortest)通常不会放入changelog中。

scope用于说明 commit 影响的范围,可选值。通常是文件、路径、功能等。对于Angular项目已经定死了scope: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope

subject是 commit 目的的简短描述,不超过50个字符。如用英语表述:

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

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

Footer 部分只用于两种情况:

  • Break Changes
  • Closes

Break Changes范例:

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.

Closes范例:

Closes #123, #245, #992

自动化工具处理git commit

手写上述的commit格式很明显并不怎么方便,而且还有出错的可能性(尽管git支持template功能,但是实际使用的时候仍然不是特别方便),为什么不交给自动化工具完成呢?

下面就是重点要介绍的规范化git commit消息的工具commitizen。

commitizen本质上是一个通用的规范化git commit的框架,通过各种Adapter实现格式化成对应格式。比如希望格式化成Angular的commit格式,那么需要额外安装cz-conventional-changelog这个adapter。目前commitizen实现的Adapter有Angular, ESlint, mapbox, jira等等,本篇我们主要使用cz-conventional-changelog实现Angular的commit格式。

由于commitizen及其生态都是使用NodeJS开发的工具,天然对NodeJS项目友好,并且附加全局命令行工具可供其他项目使用。因此本篇文档我们将分开探讨,NodeJS项目和非NodeJS项目如何使用commitizen。

使用commitizen系列工具前,请先确保系统当前安装有NodeJS的LTS版本(当前最新LTS为v10.15.3)。

NOTE: Windows环境下你需要使用cmdpowershell运行交互式终端,在cygwin/mingw32/msys2等模拟posix运行环境下无法正常执行交互式终端菜单。

NOTE: 你可能会注意到commitizen使用的快速使用的范例为npx git-cz。特别注意git-cz和commitizen是两个独立包,并且是不同开发者维护。可以将git-cz这个包看做是简化版的commitizen+cz-conventional-changelog。这个包产生的git-cz/git cz命令开箱即用,依赖轻,安装速度快,默认即使用Angular格式,默认自动忽略scope,无需配置Adapter。而使用commitizen+cz-conventional-changelog需要配置Adapter,相对依赖较重,但是对NodeJS项目比较友好,自动化支持度高。由于commitizen安装也会同时释放两个命令commitizengit-cz,注意不要和git-cz带的这个命令混淆了。

NodeJS项目

对于NodeJS项目,commitizen可以将自己的一些脚本添加到package.json中,方便npm script生命周期管理。

快速将一个项目初始化为commitizen友好的项目(需要确保当前工程中必须存在package.json文件):

 # 将commitizen命令行安装到全局(也可以用npx替代,或安装到项目的Dev依赖)
npm install commitizen -g# 使用commitizen命令初始化当前工程为commitizen友好的工程
commitizen init cz-conventional-changelog --save-dev

执行完毕后可以发现在package.jsondevDependencies配置多了cz-conventional-changelog依赖,同时,也增加了以下配置段:

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

此时git cz将出现类似于下面的交互式终端:

cz-cli@3.1.1, cz-conventional-changelog@2.1.0Line 1 will be cropped at 100 characters. All other lines will be wrapped after 100 characters.? Select the type of change that you're committing: (Use arrow keys)
❯ feat:     A new featurefix:      A bug fixdocs:     Documentation only changesstyle:    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 featureperf:     A code change that improves performancetest:     Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)

image

按照之前的Angular commit规范格式交互式输入信息即可,是不是比手写方便了许多?

以后,只要是需要git commit的地方,通通替换为git czgit-cz即可这样交互式的输入符合Angular commit规范的git log了。其余commit的参数也兼容,比如-a--amend等等。

自动检测commit是否符合规范

尽管我们可以在CI测试阶段检测commit是否符合这个规范,但是能在本地就有反馈不是更快吗?因此我们可以考虑在git commithook中加入commitlint检测,不符合commit规范的提交在本地就无法提交进去。

对于NodeJS项目来说,有个非常简单的使用git hook的项目husky,使用者无需手工定义繁琐的git hook脚本,直接在package.json中定义要执行的hook命令即可。

在项目依赖中添加huskycommitlint相关依赖:

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

然后在package.json配置中添加husky的git hook配置:

{"husky": {"hooks": {"commit-msg": "commitlint -x @commitlint/config-conventional -E HUSKY_GIT_PARAMS"}}
}

这样如果使用普通的git commit提交了不符合commit规范的消息,就会被直接打回:

 git commit -a -m '添加husky和commitlint依赖'
husky > commit-msg (node v10.15.3)⧗   input: 添加husky和commitlint依赖
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]
✖   found 2 problems, 0 warnings(Need help? -> https://github.com/conventional-changelog/commitlint#what-is-commitlint )husky > commit-msg hook failed (add --no-verify to bypass)

我看可以看到git commit触发了husky的hook,告诉用户这条commit记录不符合Angular规范。

再次使用git cz提交一次:

 git cz -a
cz-cli@3.1.1, cz-conventional-changelog@2.1.0Line 1 will be cropped at 100 characters. All other lines will be wrapped after 100 characters.? Select the type of change that you're committing: build:    Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
? What is the scope of this change (e.g. component or file name)? (press enter to skip)package.json
? Write a short, imperative tense description of the change:添加husky和commitlint提交前检测
? Provide a longer description of the change: (press enter to skip)? Are there any breaking changes? No
? Does this change affect any open issues? Nohusky > commit-msg (node v10.15.3)⧗   input: build(package.json): 添加husky和commitlint提交前检测
✔   found 0 problems, 0 warnings(Need help? -> https://github.com/conventional-changelog/commitlint#what-is-commitlint )[master bd79828] build(package.json): 添加husky和commitlint提交前检测2 files changed, 1357 insertions(+), 7 deletions(-)

符合commit规范的提交可以成功提交到版本库中。

NOTE: 巧妙合理利用husky的hook功能可以大大规范化开发。比如在pre-commit
这个hook中加入各种lint(eslink, tslink, jslint等)检测,大大提高代码规范化效率,减少BUG产生。

非NodeJS项目

对于非NodeJS项目,可以将commitizencommitlint等这些工具安装为全局的命令行工具分开使用。

安装commitizen为全局:

npm install -g commitizen cz-conventional-changelog# 注: powershell使用下面命令产生的文件是UTF16格式,需要手工转为UTF8保存
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

NOTE: 前面提到过,如果使用git-cz,则无需安装commitizen和相关Adapter,也无需配置~/.czrc,但是交互式commit的时候不会提示scope,和直接使用npx git-cz运行效果等效。

然后像git commit那样直接使用git czgit-cz就可以弹出交互式提示了:

 git add new.mdgit cz
cz-cli@3.1.1, cz-conventional-changelog@2.1.0Line 1 will be cropped at 100 characters. All other lines will be wrapped after 100 characters.? Select the type of change that you're committing: (Use arrow keys)
❯ feat:     A new featurefix:      A bug fixdocs:     Documentation only changesstyle:    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 featureperf:     A code change that improves performancetest:     Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)

检测commit是否符合规范

同样可以将commitlint安装到全局,以命令行方式在本地手工检测运行。

npm install -g @commitlint/cli @commitlint/config-conventional

每次commit之后可以使用下述命令检测:

commitlint -x '@commitlint/config-conventional' -e

-e/--edit参数代表读取git commit最后一条记录。如果希望检测最近几条commit记录,可以用:

commitlint -x '@commitlint/config-conventional' -f HEAD~1

-f/--from参数可以指明从哪一条commit记录开始检测,还可以配合-t/--to参数检测一个commit区间段。

NOTE: 如果不介意非NodeJS项目下多一堆NodeJS项目相关的配置文件,也可以在npm init初始化成nodejs项目之后走上述NodeJS项目的配置流程。

版本发布

重头戏来了。规范化commit记录的作用就是为了方便我们知道每次发布之后到底改了什么内容。利用conventional-changelog这个工具可以很方便的帮我们产生changelog。

npm install -g conventional-changelog-cli

如果之前每次commit都使用规范化的commit提交,那么使用:

conventional-changelog -p angular

应该看到这样的markdown:

#  (2019-04-25)### Bug Fixes* **third.md:** 添加新的third.md文件,添加一个新功能 719c542### Features* **new.md:** 添加新的功能项 43d6584
* **README.md:** 初始化项目工程 69c6c9f### BREAKING CHANGES* **new.md:** 这个功能打破了一个函数。before: old, new: new

这就是一个基本的CHANGELOG.md雏形,你可以自己复制到CHANGELOG.md并进行相应的修改。也可以直接输出到CHANGELOG.md文件中:

conventional-changelog -i CHANGELOG.md -s -p angular

终端中看到的内容将输出到CHANGELOG.md文件。再次使用上述命令可以将新的change log追加到文件中。可以追加-r 0参数代表将commit记录从头至尾全部生成changelog。

更自动化的发布方式standard-version

在conventional-changelog的官方文档中,官方更鼓励使用更上层的工具standard-version来产生CHANGELOG.mdconventional-changelog可以帮助我们快速检查要生成的CHANGELOG.md的格式是否符合期望,而standard-version可以自动帮助我们做以下几件事情:

  • 升级元数据中的版本号(如package.json,composer.json等等)
  • 使用conventional-changelog更新 CHANGELOG.md
  • 提交package.json (如果有) 和 CHANGELOG.md
  • 给新版本打一个tag

首先安装standard-version到全局命令行:

npm i -g standard-version

执行下standard-version,将看到类似于下面这样的输出:

 standard-version
✔ created CHANGELOG.md
✔ outputting changes to CHANGELOG.md
✔ committing CHANGELOG.md
✔ tagging release v2.0.0
ℹ Run `git push --follow-tags origin master && npm publish` to publish

可以非常清楚的从终端上看到standard-version做了哪些事情。检查git log可以看到新增了一条commit记录:

commit cac4b5cda4f0c2a78928d8306c5c2eab8c590f02 (HEAD -> master, tag: v2.0.0)
Author: Your Name <you@example.com>
Date:   Thu Apr 25 17:15:56 2019 +0800chore(release): 2.0.0

项目中也生成了一个CHANGELOG.md文件:

# Change LogAll notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.#  (2019-04-25)### Bug Fixes* **third.md:** 添加新的third.md文件,添加一个新功能 719c542### Features* **new.md:** 添加新的功能项 43d6584
* **other.md:** 新增一个other.md文件,记录了新的内容 1a204d9
* **README.md:** 初始化项目工程 69c6c9f### BREAKING CHANGES* **new.md:** 这个功能打破了一个函数。before: old, new: new

standard-version一些基本用法

直接跟空参运行的行为我们已经看到了,一些基本参数介绍下:

  • --dry-run: 强烈建议正式运行之前先加这个参数,打印一下要做的事情,并不真正执行
  • --first-release/-f: 首次发布,加上这个参数代表不会升级版本号。仅第一次使用需要
  • --commit-all/-a: 等效于git commit -a,建议自己决定要提交哪些文件,都add没问题之后再执行standard-version
  • --release-as/-r: 手工指定下一个版本号(格式<major|minor|patch>)。这个参数可能会经常使用。standard-version默认规则是从major/minor/patch中最后一个非零的字段开始累加,如v1.0.0 -> v2.0.0v1.1.0 -> v1.2.0v1.1.1 -> v1.1.2,指定这个参数可以规避这个规则,从自定义的版本号开始重新按上述规则升级
  • --prerelease/-p: 预发布版本,默认产生的tag像这样: v1.0.1-0。可以跟上一个可选的tag id。如-p alpha,将产生这样的tag: v1.0.1-alpha.0

项目实战Workflow[1]

对于实际的项目,可以采用这一套流水线规范化代码提交与发布流程。需要初始化项目。首先安装全局依赖,仅首次需要:

# 等standard-version的BUG修复了考虑将conventional-changelog替换为standard-version
npm install -g commitizen

NodeJS项目

对于NodeJS项目需要初始化为commitizen友好的项目,以及添加husky的hook检查:

commitizen init cz-conventional-changelog --save-dev
npm i -D husky @commitlint/config-conventional @commitlint/cli

然后在package.json配置中添加husky的git hook配置:

{"husky": {"hooks": {"commit-msg": "commitlint -x @commitlint/config-conventional -E HUSKY_GIT_PARAMS"}}
}

如有需要也可以在pre-commit这个hook中添加各种lint检测。

今后使用git-cz/git cz代替git commit提交代码。

非NodeJS项目

cz-conventional-changelog,commitlint添加到全局:

npm install -g cz-conventional-changelog @commitlint/config-conventional @commitlint/cli

默认commitizen的Adapter为cz-conventional-changelog:

# 注: powershell使用下面命令产生的文件是UTF16格式,需要手工转为UTF8保存
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

使用git-cz/git cz代替git commit提交代码

使用commitlint -x @commitlint/config-conventional -e检测最新一条commit记录是否符合规范。

NOTE: 不在意非NodeJS项目下多一堆nodejs项目相关的文件,也可以在npm init初始化成nodejs项目工程之后走上述NodeJS项目方案

版本发布

安装standard-version到全局

npm install -g standard-version

使用以下命令生成CHANGELOG.md,并自动打tag:

standard-version --dry-run  # 加上--dry-run检查是否符合预期
standard-version

默认规则自动升级小版本号,如需手工指定版本号,可以追加-r x.y.z这样的参数,第一次发布也可以追加-f参数,表示不升级当前版本。更详细的standard-version用法可以参考之前更自动化的发布方式standard-version小节的内容。

CI检测

在gitlab ci中运行以下命令检测当前提交是否符合conventional-changelog规范:

npx -p "@commitlint/cli" -p "@commitlint/config-conventional" -p "commitlint-format-junit" commitlint -x @commitlint/config-conventional -o commitlint-format-junit -f ${CI_COMMIT_BEFORE_SHA} > commitlint_result.xml

将lint result输出为JUnit格式,方便Gitlab在merge request的时候展示lint失败的结果。

vscode用户

可以安装vscode-commitizen插件,使用ctrl+shift+pcommand+shift+p使用conventional commit提交代码。

image.png

image.png

参考资料:

  • Git Commit Best Practices
  • AngularJS的git-commit规范推广
  • Commit message 和 Change log 编写指南
  • The way to fully automated releases in open source projects

规范化git commit信息相关推荐

  1. 写好 Git Commit 信息的 7 个建议

    介绍: 为什么好的提交信息如此重要 当你随意浏览任一 git 仓库的日志,你很可能会发现其中的提交信息或多或少有点乱.举个例子,瞧一瞧我早先提交到 Spring 上的这些宝贝: $ git log - ...

  2. Git撤销已经推送(push)至远端仓库的提交(commit)信息

    原文链接:https://blog.csdn.net/hanchao5272/article/details/79435730 有关修改提交(git commit)信息的方法可以参考: Git com ...

  3. 如何规范你的Git commit?

    简介:commit message应该如何写才更清晰明了?团队开发中有没有遇到过让人头疼的git commit?本文分享在git commit规范建设上的实践,规定了commit message的格式 ...

  4. git commit 规范校验配置和版本发布配置

    一. 快速配置和版本发布流程 该章节主要是对下文内容的归纳方便往后的查阅,如果需要了解细节部分请从第二章节开始阅读 1.1 依赖包安装 # husky 包安装 npm install husky -- ...

  5. Git commit hook 规范标准配置

    Git每次提交代码都需要写commit message,否则就不允许提交.一般来说,commit message应该清晰明了,说明本次提交的目的,具体做了什么操作--但是在日常开发中,大家的commi ...

  6. git commit 、CHANGELOG 和版本发布的标准自动化

    一直以来,因为团队项目迭代节奏很快,每次发布的更新日志和版本更新都是通过人肉来完成的.有时候实在忙的团团转,对于手动的写这些更新信息就显得力不从心了.对于团队新来的小伙伴,有时候遇到些紧急情况,就更显 ...

  7. git 只commit不push 会有影响吗_规范化团队 git 提交信息

    规范化团队 git 提交信息 同一个工程项目,为了方便管理,git 的 commit 信息最好按照一定的格式规范,以便在需要的时候方便使用.什么是方便的时候,比如出现了一个线上 bug,所以需要回滚操 ...

  8. 修改git历史提交的commit信息

    本文是基于idea的操作,亲测可用 前言: 很多公司都会自定义 Git - 使用强制策略,那么他的commit信息就会有固定的格式,一旦不是这个格式,就会出现push失败 但是push失败,很多也只在 ...

  9. git commit –a时使用vim编辑提交信息

    今天在公司使用git commit 向git server 提交代码,发现使用git-commit -a命令后直接打开了nano编辑器. 没有用过nano,果断放弃改用vim. vim ./.git/ ...

最新文章

  1. 用createrepo配置Yum本地源
  2. Linux下区分物理CPU、逻辑CPU和CPU核数
  3. 【API进阶之路】帮公司省下20万调研费!如何巧用情感分析API实现用户偏好调研
  4. tushare pro接口_Python与交易策略分析amp;tushare/baostock库介绍(附代码)
  5. Vue简介及HelloWord编写
  6. 光动能表怎么维护_[腕表]西铁城CITIZEN AT814451E 光动能 电波表 开
  7. python获取指定日期的前N天日期和后N天日期
  8. PacketSender —— TCP/UDP 包测试工具
  9. 使用XPO过程中的代码优化
  10. 超级列表框排序mysql_超级列表框排序
  11. Servlet chapter 1
  12. .net 考试系统人一多就断开了_【项目】Java在线考试系统
  13. python-白盒测试方法
  14. 修复谷歌浏览器翻译插件无法使用的问题
  15. html中的文字透明背景图片,利用css实现背景透明和文字不透明效果汇总
  16. 一个https神奇的故事
  17. 计算机从系统格式开始
  18. python 根据坐标点计算方位角函数
  19. sql(Mysql)查询出时间数据在显示时加上时区
  20. edgeR/limma/DESeq2差异基因分析→ggplot2作火山图→biomaRt转换ID并注释

热门文章

  1. excel按季度分类汇总_excel进行分类汇总的五种方法
  2. 艺术设计、设计学考研(成都片区)
  3. vue+mintui+picker弹框选择器
  4. vue选择图片的几种方式
  5. 十余年陪伴NS-2的心得体会
  6. 期货十三篇 第七篇 平仓篇
  7. 社交电商是做什么的?新手如何做社交电商?
  8. 联想电脑尺寸在哪里看_联想笔记本型号在哪里看 笔记本电脑品牌有哪些
  9. android开发游记:图片的上传下载-使用七牛云存储管理图片
  10. Java 2023发展趋势