git commit 工具链
前言
如果你待过 大厂 或者看过一些 社区规范,会发现前端在 commit 时有对应的规范。
规范 一方面方便管理项目,一方面能让评审人员或者自己在看对应 commit 时,能快速定位到做的事情。
像一些社区的cli内置了 Eslint ,例如Vue cli、Vite、create react app等,可以根据你的需求选配。但是这里,我们自己来搭配 Eslint 。
代码规范
Eslint
用过的同学对它都不陌生,Eslint可以在你开发期间检测的你代码的是否按照规范写,如果不是,就会有报错提醒。
安装
npm i eslint -D
生成配置文件
npx eslint --init
eslint 检测风格
- To check syntax only - 只检查语法
- To check syntax and find problems - 检查语法和查找错误
- To check syntax, find problems, and enforce code style - 检查语法,查找错误并加强代码风格
项目使用的模块规范
项目使用的框架
是否使用 TypeScript
代码运行环境
配置文件类型
是否用 npm 安装规范
选择你的 npm 镜像容器
选配完成后,会在根目录会自动生成 .eslintrc.js
module.exports = {
env: {
browser: true,
node: true,
es2021: true
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:@typescript-eslint/recommended"
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: "latest",
sourceType: "module"
},
plugins: ["react", "@typescript-eslint"],
// 配置规则
rules: {}
};
Vscode eslint自动格式化
保存代码的时候,自动运行 eslint 格式化
旧版本
{
//配置eslint
"eslint.autoFixOnSave": true, // 启用保存时自动修复,默认只支持.js文件
"eslint.validate": [
"javascript", // 用eslint的规则检测js文件
{
"language": "vue", // 检测vue文件
"autoFix": true // 为vue文件开启保存自动修复的功能
},
{
"language": "html",
"autoFix": true
}
]
}
新版(>1.41.0)配置
{
//autoFixedOnSave 设置已废弃,采用如下新的设置
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.format.enable": true,
//autoFix默认开启,只需输入字符串数组即可
"eslint.validate": ["javascript", "vue", "html"]
}
prettier
使用 prettier 插件, 通过配置 prettier 的配置文件,统一项目的格式化风格
安装
没有 eslint
npm i prettier -D
有 eslint
npm i prettier eslint-config-prettier eslint-plugin-prettier -D
测试是否安装成功
prettier -v
文件格式
自定义文件的格式可以有多种
- prettierrc 文件,支持yaml和json格式;或者加上扩展名也可以,可选的扩展名有 .yaml/.yml/.json
- prettierrc.toml 文件
- prettier.config.js or .prettierrc.js 返回一个对象
- package.json文件中加上prettier对象
json 配置文件写法
{
"semi": false,
"singleQuote": true
}
toml 文件写法
# .prettierrc.toml
semi = false
singleQuote = true
yaml 文件写法
# .prettierrc
semi: false
singleQuote: true
js 写法
// prettier.config.js or .prettierrc.js 返回对象
module.exports = {
semi: false,
singleQuote: true
};
配置文件
在根目录创建 .prettierrc, 配置格式化
// .prettierrc
{
"semi": false,
"tabWidth": 2,
"trailingComma": "none",
"singleQuote": true,
"arrowParens": "avoid"
}
prettier 配置大全
// 常用配置相关解释
printWidth: 100, // 超过最大值换行
tabWidth: 4, // 缩进字节数
useTabs: false, // 缩进不使用tab,使用空格
semi: true, // 句尾添加分号
singleQuote: true, // 使用单引号代替双引号
proseWrap: "preserve", // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
arrowParens: "avoid", // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
disableLanguages: ["vue"], // 不格式化vue文件,vue文件的格式化单独设置
endOfLine: "auto", // 结尾是 \n \r \n\r auto
eslintIntegration: false, //不让prettier使用eslint的代码格式进行校验
htmlWhitespaceSensitivity: "ignore",
ignorePath: ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
jsxBracketSameLine: false, // 在jsx中把'>' 是否单独放一行
jsxSingleQuote: false, // 在jsx中使用单引号代替双引号
parser: "babylon", // 格式化的解析器,默认是babylon
requireConfig: false, // Require a 'prettierconfig' to format prettier
stylelintIntegration: false, //不让prettier使用stylelint的代码格式进行校验
trailingComma: "es5", // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
tslintIntegration: false // 不让prettier使用tslint的代码格式进行校验
有时候,某些文件/文件夹的文件并不需要格式化,我们可以通过配置 .prettierignore 来忽略不需要格式化的文件,常见配置如下:
// .prettierignore
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
运行prettier
命令
npx prettier --write <文件路劲+文件名>
//例如,格式化当前路劲下的aaa.js文件
npx prettier --write ./aaa.js
格式化全部
npx prettier --write .
格式化某个文件
npx prettier --write ./文件夹路径/文件名
格式化某个文件夹
npx prettier --write ./文件夹路径
VsCode 插件
git 规范
社区规范
社区认可的 commit 规范
feat: 新增 feature
fix: 修复 bug
docs: 仅仅修改了文档,比如 README, CHANGELOG, CONTRIBUTE等等
style: 仅仅修改了空格、格式缩进、逗号等等,不改变代码逻辑
refactor: 代码重构,没有加新功能或者修复 bug
perf: 优化相关,比如提升性能、体验
test: 测试用例,包括单元测试、集成测试等
chore: 改变构建流程、或者增加依赖库、工具等
revert: 回滚到上一个版本
build: 更新包的内容
release: release版本更新
书写格式如下:
type(scope): <subject>
例子:
revert: feat(form): add 'validate' option
最简写法:feat: add 'validate' option
但是每次手动 commit 都要写上对应的 type ,挺麻烦的?我们也可以用对应的插件来帮我们做类似的事,往下看。
git hooks
git Hooks它是一些自定义的脚本,用于控制git工作的流程,分为客户端钩子和服务端钩子,这里我们主要介绍客户端钩子
客户端钩子分为很多种。 下面把它们分为:提交工作流钩子、电子邮件工作流钩子和其它钩子。主要介绍提交工作流钩子:pre-commit、prepare-commit-msg、commit-msg、post-commit。
- pre-commit(常用)
在键入提交信息前运行。 它用于检查即将提交的快照。例如,检查是否有所遗漏,确保测试运行,以及核查代码。 如果该钩子以非零值退出,Git 将放弃此次提交,不过你可以用 git commit --no-verify 来绕过这个环节。 你可以利用该钩子,来检查代码风格是否一致(运行类似 lint 的程序)、尾随空白字符是否存在(自带的钩子就是这么做的),或新方法的文档是否适当。
- prepare-commit-msg
在启动提交信息编辑器之前,默认信息被创建之后运行。 它允许你编辑提交者所看到的默认信息。 该钩子接收一些选项:存有当前提交信息的文件的路径、提交类型和修补提交的提交的 SHA-1 校验。 它对一般的提交来说并没有什么用;然而对那些会自动产生默认信息的提交,如提交信息模板、合并提交、压缩提交和修订提交等非常实用。 你可以结合提交模板来使用它,动态地插入信息。
- commit-msg(常用)
接收一个参数,此参数即上文提到的,存有当前提交信息的临时文件的路径。 如果该钩子脚本以非零值退出,Git 将放弃提交,因此,可以用来在提交通过前验证项目状态或提交信息。
- post-commit
在整个提交过程完成后运行。 它不接收任何参数,但你可以很容易地通过运行 git log -1 HEAD 来获得最后一次的提交信息。 该钩子一般用于通知之类的事情。
git hooks安装
当你用git init初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本,进入.git/hooks后会看到一些hooks的官方示例,他们都是以.sample结尾的文件名。
git hooks存储位置
git hooks被存储在Git目录下的.hooks子目录中,即绝大部分项目中的.git/hooks。
调用git hooks
注意这些以.sample结尾的示例脚本默认是不会执行的,只有把一个正确命名(不带扩展名.sample)且可执行的文件放入 .git/hooks 目录中,才会激活该钩子脚本,生效且被git调用。像我们平常用的 git push、git commit 等命名都是用到了 hooks
本地.git/hooks的缺陷
【不能共享】由于.git文件夹是不会被git跟踪的,所以.git/hooks目录下的hooks钩子无法提交,就不能和他人共享钩子脚本。
git 工具链
前面我们已经了解 社区规范 和 git hooks ,那我们可以利用一些 git 工具 来帮我们统一 git commit 规范。
-
husky
- 操作 git 钩子的工具
-
lint-staged
- 本地暂存代码检查工具
-
commitlint
- commit 信息校验工具
-
commitizen
- 辅助 commit 信息 ,就像这样,通过选择输入,规范提交信息
husky
安装 husky
npm install husky --save-dev
在 package.json 中添加脚本,自动启用Git钩子
npm set-script prepare "husky install" // 会在 package.json 中的 scripts 里新增一个 prepare 命令
启用 husky
npm run prepare
// 或
npx husky install
执行完上述命令,会发生几个变化:
- 在
.git同级目录生成.husky文件夹 - 在
package.json中的scripts中添加了"prepare": "husky install" - 更改
git配置项core.hooksPath为.husky
配置完 husky 后,我们可以去配置 对应的一些 hook
配置 husky 的方式,默认使用的配置是 .husky文件夹里对应的 hooks
-
- 更改hooks脚本
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
// 脚本执行了 lint-staged 插件检测
npm run lint-staged
-
- 修改package.json
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,vue}": [
"eslint --fix",
"git add ."
]
},
pre-commit
配置前置钩子,这里我们用 lint-staged 来做前置校验
添加 pre-commit 钩子
npx husky add .husky/pre-commit "npx lint-staged"
输完命令后,会在 .husky 下新增一个 pre-commit 文件,里面执行了 npx lint-staged 命令
配置 lint-staged,有两种配置方法
-
.lintstagedrc.json
在根目录下新建
.lintstagedrc.json,运行 npx lint-staged 会读取这个文件里边的配置,配置如下// 这里是全局匹配了,可以指定对应文件夹,例如 src/**/*.{ts,vue} { "*.{js,jsx,ts,tsx}": ["prettier --write .", "eslint --fix"], "*.md": ["prettier --write"], }这个配置做了什么? 匹配 git add 暂存区里对应后缀名的文件,然后执行 prettier格式化,eslint检测
-
package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["prettier --write .", "eslint --fix"],
"*.md": ["prettier --write"]
}
}
commit-msg
添加 commit-msg,这里用的是 commitlint,添加钩子使用 husky add 命令
// 添加 commitlint hook
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
配置 commitlint 提交规范,新增 commitlint.config.js
// commitlint.config.js
module.exports = { extends: ["@commitlint/config-conventional"] };
做的事情,跟上边差不多。 commitlint 会校测你提交的 commit message 是否符合规范,默认是Angular的提交规范
| 类型 | 描述 |
|---|---|
| build | 编译相关的修改,例如发布版本、对项目构建或者依赖的改动 |
| chore | 其他修改, 比如改变构建流程、或者增加依赖库、工具等 |
| ci | 持续集成修改 |
| docs | 文档修改 |
| feat | 新特性、新功能 |
| fix | 修改bug |
| perf | 优化相关,比如提升性能、体验 |
| refactor | 代码重构 |
| revert | 回滚到上一个版本 |
| style | 代码格式修改, 注意不是 css 修改 |
| test | 测试用例修改 |
也可以自己写校验方法,来检验校验内容,例如我写的校验在 verifyCommit.js,那添加的时候设置一下就行,代码如下
npx husky add .husky/commit-msg 'node [dir]/verifyCommit.js' # 指定目录文件
或者改 package.json 的配置
{
"husky": {
"hooks": {
"commit-msg": "node [dir]/verifyCommit.js"
}
}
}
commitlint-config-cz
通过 commitlint-config-cz 可以定义commitlint 的提交规范
安装
npm i -D commitlint-config-cz cz-customizable
修改 commitlint.config.js 提交规范,改为 cz
// 采用 cz 自定义的提交规范, > .cz-config.js
module.exports = { extends: ["cz"] };
增加 .cz-config.js
"use strict";
module.exports = {
types: [
{ value: "✨feat", name: "新增: 新的内容" },
{ value: "🐛fix", name: "修复: 修复一个Bug" },
{ value: "📝docs", name: "文档: 变更的只有文档" },
{ value: "💄style", name: "格式: 空格, 分号等格式修复" },
{ value: "♻️refactor", name: "重构: 代码重构,注意和特性、修复区分开" },
{ value: "⚡️perf", name: "性能: 提升性能" },
{ value: "✅test", name: "测试: 添加一个测试" },
{ value: "🔧chore", name: "工具: 开发工具变动(构建、脚手架工具等)" },
{ value: "⏪revert", name: "回滚: 代码回退" },
{ value: "🏆build", name: "打包: 更新包内容" },
{ value: "🌀release", name: "更新: 版本更新" }
],
scopes: [
{ name: "leetcode" },
{ name: "javascript" },
{ name: "typescript" },
{ name: "Vue" },
{ name: "node" }
],
// it needs to match the value for field type. Eg.: 'fix'
/* scopeOverrides: {
fix: [
{name: 'merge'},
{name: 'style'},
{name: 'e2eTest'},
{name: 'unitTest'}
]
}, */
// override the messages, defaults are as follows
messages: {
type: "选择一种你的提交类型:",
scope: "选择一个scope (可选):",
// used if allowCustomScopes is true
customScope: "Denote the SCOPE of this change:",
subject: "短说明:\n",
body: '长说明,使用"|"换行(可选):\n',
breaking: "非兼容性说明 (可选):\n",
footer: "关联关闭的issue,例如:#31, #34(可选):\n",
confirmCommit: "确定提交说明?(yes/no)"
},
allowCustomScopes: true,
allowBreakingChanges: ["特性", "修复"],
// limit subject length
subjectLimit: 100
};
在 package.json 中, 新增 config 配置,修改 commitizen 使用的容器
"config": {
"commitizen": {
"path": "node_modules/cz-customizable"
}
},
新增命令 commit 命令
// package.json
"scripts": {
"commit": "git-cz"
},
执行命令, npm run commit