前端工程化之 git commit 工具链

简介: 前端工程化之 git commit 工具链

前言


最近在做 monorepo 项目的前端工程化,其中有一个部分与 git commit 有关,因此参考了几个项目,总结出了相关的工具链,并写成文章。

整个工具链,都是围绕着 git commit message 的生成、校验,到最后的生成 changelog 的过程


下面是我调研的几个库在该过程所使用到的一些工具:

tdesign-vue-next-starter ant-design-vue vue vite
commit 规范 angular 规范 angular 规范 基于 angular 规范的扩展规范 基于 angular 规范的扩展规范
生成 commit message commitizen × × ×
校验 commit message commitlint commitlint 使用自定义脚本校验 使用自定义脚本校验
生成 changelog × 自定义脚本 conventional-changelog conventional-changelog

除了使用项目中自定义的一些工具外,主要使用到的开源工具为以下几个:

  • commitizen:生成 commit message
  • commitlint:校验 commit message
  • conventional-changelog:生成 changelog

在介绍这几个工具前,先介绍一下目前用得比较多的 commit 规范


angular commit 规范


网上就有很多文章,大家应该也是非常熟悉的,不了解的可以看看阮一峰的文章。该小节的内容都来源于该文章,这里我把一些重点的内容列一下

Commit message 包括三个部分:Header,Body 和 Footer。


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

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

Header 中 type 的类别,有以下 7 种:

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

Body 部分是对本次 commit 的详细描述,可以分成多行。

Footer 部分只用于两种情况:

  • 不兼容变动,以 BREAKING CHANGE 开头,后面是对变动的描述、以及变动理由和迁移方法
  • 关闭 Issue

另外,如果是回滚撤销 git commit,则 commit message 必须要以 revert: 开头,如:


revert: feat(pencil): add 'graphiteWidth' option
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.

commit 工具链


  • commitizen:生成 commit message
  • commitlint:校验 commit message
  • conventional-changelog:生成 changelog

这些工具,作用不同,那么要如何把这些工具的流程串起来?我们先来看看 git commit 的周期钩子

1686385808110.png

下面是简单的 git 钩子介绍,详情请查看官方文档

  • pre-commit 钩子:在键入提交信息前运行,可以用于 eslint 等 linter 的代码校验和修复
  • prepare-commit-msg 钩子:在启动提交 commit message 编辑器之前运行。可以在该阶段生成 commit message(commitizen 在该阶段运行),这样就不会打开编辑器输入 commit message 了
  • commit-msg 钩子:填写 commit message 之后运行,如果该钩子的脚本以非零值退出,则 Git 放弃提交。可用于校验 commit message 是否符合规范。(commitlint 在该阶段运行)
  • post-commit 钩子:Git commit 提交过程完成后执行

changelog 的生成并没有在 git 钩子中,因为不是每次 commit 都需要生成 changelog,只需要再发布新的版本前生成即可


commitizen


通过命令行交互的方式,生成 git commit message

在使用 commitizen 前,首先得告诉 commitizen 我们用的是哪个 commit 规范,因此我们可以做以下配置:

  1. 安装依赖,假设我们使用 cz-conventional-changelog 作为配置,更多配置可以查看这里


npm install commitizen cz-conventional-changelog --save
  1. 在 package.json 中,加入 commitizen 的配置


{
  "script":{
      "cz": "cz"
  }
  "config": {
    "commitizen": {
      "path": "cz-conventional-changelog"
    }
  }
}

这样 commitizen 就知道我们所使用的的规范了

  1. 生成 commit message 并提交 commit:


npx cz
## 运行结果如下:
? Select the type of change that you are committing: feat:     A new feature
? What is the scope of this change (e.g. component or file name): (press enter to skip)
? Write a short, imperative tense description of the change (max 94 chars): test
? Provide a longer description of the change: (press enter to skip)
? Are there any breaking changes? No
? Does this change affect any open issues? No
## commit message: feat: test

命令行交互的内容,是来源于配置  cz-conventional-changelog ,因为不同的 commit 规范,有不同的命令行交互

命令行交互效果图如下:

1686385693719.png

如何与 git 钩子配合使用?

配置 prepare-commit-msg 的 git 钩子


# .git/hook/prepare-commit-msg
exec < /dev/tty && node_modules/.bin/cz --hook || true

这样 git-commit 的时候,就会执行 cz,进行命令行交互式地生成 commit 信息

  • exec < /dev/tty,默认情况下,git钩子不是交互式的。这个命令允许用户在钩子期间使用他们的终端与commizen交互。
  • --hook 是告诉 commitizen,这是在 git 钩子中运行的(直接命令行执行 cz 会生成 commit message 并提交 commit,如果通过 git 钩子触发,则是只负责生成 commit message,传给 git commit 命令)

commitlint


类似 eslint,commitlint 则是对 commit message 进行规范校验。

同样的,commitlint 也需要一份配置,告诉它我们需要用的是哪个规范。配置 commitlint 的方式如下:


// 项目根目录创建配置文件
// commitlint.config.js
module.exports = { extends: ['@commitlint/config-conventional'] };

这里是用的是配置 @commitlint/config-conventional ,其他配置可以查看官方文档

commitlint 就必须得配合 git 钩子使用了,需要在 git commit 信息生成/填写之后,再执行校验。因此使用的 git 钩子是 commit-msg


# .git/hooks/pre-commit
npx commitlint -e $1
• $1,传入命令行的第一个参数,在 commit-msg 的 git 钩子中,为 .git/COMMIT_EDITMSG,该文件存储的是当次 commit 的 message 文本
• commitlint -e 文件路径:从文件中读取 git commit message 文本

git 钩子的同步


我们的 git commit 钩子是写在 .git/hooks 目录下的,当运行 git commit 的时候就会被运行

但是,git 的客户端钩子(commit 的几个钩子都是),不会被提交到 git 仓库中,这就意味着,别人 clone 了这个仓库,钩子是没有被复制过去的

为了解决这个痛点,我们需要使用一些辅助工具去同步我们的 git 钩子,常用的工具有 huskysimple-git-hooks

这里以 simple-git-hooks 为例,说明一下如何配置:

  1. 安装依赖


npm install simple-git-hooks --save-dev
  1. 配置 package.json


{
  "simple-git-hooks": {
    "pre-commit": "npx lint-staged",
    "prepare-commit-msg": "exec < /dev/tty && node_modules/.bin/cz --hook || true",
    "commit-msg": "npx commitlint -e $1",
  }
}
  1. 手动运行一下命令,安装钩子到 .git/hooks


npx simple-git-hooks

由于 package.json 会上传到 git 仓库,因此这些钩子配置也会被保存,clone 仓库之后,只需要执行安装钩子即可。


changelog 生成


生成 changelog 使用的是 conventional-changelog,只需要运行以下命令,就能生成 changlog 文件


conventional-changelog -p angular -i CHANGELOG.md -s
  • -p:angular 的 commit 规范
  • -i:选择输入的文件
  • -s:输入跟输出的文件一致

该命令会在 CHANGELOG.md 顶部,拼接上最新的一个版本的 changelog,不会修改之前的 changelog

changelog 单条内容就是单条的 git commit message,下面看看一个 changelog 的例子(节选自 @vitejs/plugin-vue),:


1686385574664.png

生成 changelog 的基本流程

  1. 根据 git tag 将 所有 commit message 进行分割,git tag 需要以 v 开头,如 v1.9.3v1.9.2
  2. 筛选出需要生成 changelog 的 commit。
  • 并非所有类型的 message 都会生成 changelog,angular 规范中,只有 featfixpref,以及 revert 回滚的 commit,会生成到 changelog 中。其他的类型,需要自己补充进去。不建议将 docschorestyle, 、refactortest 加入到 changelog
  1. 根据筛选出来的 commit message,生成最新的 tag 版本的 changelog
  • 由于允许手动修改 changelog 文件,因此默认只会生成最近一个 tag 的 changelog,因此需要参数 -i,传入上一次的 changelog 文件,然后在它的顶部,拼接上最新生成的 changelog

monorepo 项目如何生成 changelog?

由于 monorepo 工程中,存在多个 package 包,它们的 changelog 是需要各自分开的


而按照上文 changelog 的生成方式,是会读取所有 commit 然后生成,并没有对 commit 进行过滤(去掉不属于该 package 的 commit)

那因此,需要用到另外一个参数 --commit-path

conventional-changelog -p angular -i CHANGELOG.md -s --commit-path <替换为 package 目录>

这告诉 conventional-changelog,在生成 changelog 时,需要对每个 git commit 的文件进行检查,如果 commit 中变更的文件,是 commit-path 目录中的文件,则该 commit 才被认为是有效 commit,才会用于生成 changelog

1686385538981.png


上图展示了 commit 是如何通过 --commit-path 过滤 commit 的。由于最后一个 commit 中,同时修改了 A 和 B 的包,因此 A 和 B 在生成 changelog 时,都会有该 commit 的信息


总结


commit 的工具链已经介绍完毕,每个工具都有它各自的作用,我们可以看自己的需要,选择是否使用这些工具

就好像,tdesign-vue-next-starter 只是个业务模板,不是工具库,其实可以不需要 changelog(但要也行)

而 vite、vue 这些库,则没有使用 commitizen 生成 commit message,因为其实 commit message 直接手写可能更加方便(个人也认为手写更方便),因此也是不需要的。

而 commit 规范的校验,参考的这几个库,都有做到,不过方式不同,有的是 commitlint,有的是自己写的脚本,这是因为 vue 和 vite 扩展了 angular 规范,因此校验脚本也是自己写的,当然也可以用 commitlint 实现,可能是时间原因没做,也没有那么高的优先级。

实际上,我们也不必全部照搬这些,我们更多的是要理解其过程。而对于自己开发的项目,只需要结合自身需要即可。

如果这篇文章对您有所帮助,请帮忙点个赞👍,您的鼓励是我创作路上的最大的动力

目录
相关文章
|
1月前
|
前端开发 开发工具 git
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
34 5
|
2月前
|
开发工具 git
GIT:如何合并已commit的信息并进行push操作
通过上述步骤,您可以有效地合并已提交的信息,并保持项目的提交历史整洁。记得在执行这些操作之前备份当前工作状态,以防万一。这样的做法不仅有助于项目维护,也能提升团队协作的效率。
147 4
|
2月前
|
开发工具 git
GIT:如何合并已commit的信息并进行push操作
通过上述步骤,您可以有效地合并已提交的信息,并保持项目的提交历史整洁。记得在执行这些操作之前备份当前工作状态,以防万一。这样的做法不仅有助于项目维护,也能提升团队协作的效率。
242 3
|
1月前
|
前端开发 开发工具 git
搭建Registry&Harbor私有仓库、Dockerfile(八)+前端一些好学好用的代码规范-git hook+husky + commitlint
搭建Registry&Harbor私有仓库、Dockerfile(八)+前端一些好学好用的代码规范-git hook+husky + commitlint
19 0
|
2月前
|
缓存 前端开发 JavaScript
探索现代前端框架与工具链
探索现代前端框架与工具链
31 0
|
3月前
|
存储 前端开发 开发工具
前端常用的git操作
【8月更文挑战第24天】前端常用的git操作
18 1
|
3月前
|
JavaScript IDE 前端开发
前端开发工具配置 nodejs & git & IDE
前端开发工具配置 nodejs & git & IDE
|
3月前
|
开发工具 git
Git——commit的提交规范
Git——commit的提交规范
102 4
|
3月前
|
测试技术 持续交付 开发工具
[译] 为何每次 Git Commit 要尽可能小?
[译] 为何每次 Git Commit 要尽可能小?
|
3月前
|
Java 开发工具 Android开发
Android Studio利用Build.gradle导入Git commit ID、Git Branch、User等版本信息
本文介绍了在Android Studio项目中通过修改`build.gradle`脚本来自动获取并添加Git的commit ID、branch名称和用户信息到BuildConfig类中,从而实现在编译时将这些版本信息加入到APK中的方法。
71 0