前提概要
我们使用<font style="color:rgb(77, 77, 77);">husky</font>检测<font style="color:rgb(77, 77, 77);">git</font>钩子,<font style="color:rgb(77, 77, 77);">lint-staged</font>规范化暂存区代码,<font style="color:rgb(77, 77, 77);">commitlint</font>规范化提交信息。
钩子介绍
| git钩子 | 描述 | |
|---|---|---|
| pre-commit | 判断提交的代码是否符合规范 | |
| commit-msg | 判断 commit 信息是否符合规范 | |
| pre-push | 执行测试,避免对以前的内容造成影响 |
工具介绍
<font style="color:rgb(51, 51, 51);">husky</font>:操作git钩子的工具<font style="color:rgb(51, 51, 51);">lint-staged</font>:本地暂存代码检查工具<font style="color:rgb(51, 51, 51);">commitlint</font>:提交信息校验工具<font style="color:rgb(51, 51, 51);">commitizen</font>:辅助提交信息 ,全局安装后可以使用<font style="color:rgb(51, 51, 51);">cz</font>命令,选项式提交<font style="color:rgb(51, 51, 51);">git</font>
commitlin
- 安装依赖
pnpm add @commitlint/config-conventional @commitlint/cli cz-git czg -D
- 使用的版本
"devDependencies": {"@commitlint/cli": "^19.5.0","@commitlint/config-conventional": "^19.5.0","cz-git": "^1.10.1","czg": "^1.10.1"},
- 说明
@commitlint/config-conventional: 这是一个配置包,提供了一套基于 Angular 规范的提交信息格式规则。它帮助确保提交信息的一致性和可读性。
@commitlint/cli:这是 Commitlint 的命令行工具,用于检查提交信息是否符合指定的规则。通常与 @commitlint/config-conventional 一起使用。
cz-git: 这是一个 Commitizen 适配器,提供了一种交互式的方式来生成符合规范的提交信息。它可以帮助开发者在提交代码时选择合适的提交类型、描述和其他信息。
czg: 这是一个命令行工具,类似于 cz-git,提供了一个交互式的界面来生成提交信息。它通常用于简化和标准化提交信息的创建过程。
package.json更新相关代码
{"scripts": {"commit": "czg"},"commitizen": {"path": "node_modules/cz-git"}}
- 简洁版本 -
commitlint.config.cjs
const fs = require('fs');const path = require('path');/** @type {import('cz-git').UserConfig} */module.exports = {ignores: [(commit) => commit.includes('init')],extends: ['@commitlint/config-conventional'],rules: {'body-leading-blank': [2, 'always'],'footer-leading-blank': [1, 'always'],'header-max-length': [2, 'always', 108],'subject-empty': [2, 'never'],'type-empty': [2, 'never'],'subject-case': [0],'type-enum': [2,'always',['fix','docs','style','refactor','perf','test','build','ci','chore','revert','wip','workflow','types','release']]},prompt: {messages: {type: '选择你要提交的类型 :',scope: '选择一个提交范围[可选]:',customScope: '请输入自定义的提交范围 :',subject: '请简要描述提交 :\n',body: '填写更加详细的变更描述[可选]。使用 "|" 换行 :\n',breaking: '列举非兼容性重大的变更[可选]。使用 "|" 换行 :\n',footerPrefixsSelect: '选择关联issue前缀[可选]:',customFooterPrefixs: '输入自定义issue前缀 :',footer: '列举关联issue [可选] 例如: #31, #I3244 :\n',confirmCommit: '是否提交或修改commit ?'},types: [{ value: 'feat', name: 'feat: ✨ 新增功能', emoji: '✨' },{ value: 'fix', name: 'fix: 🐛 修复缺陷', emoji: '🐛' },{ value: 'docs', name: 'docs: 📝 文档变更', emoji: '📝' },{value: 'style',name: 'style: 💄 代码格式',emoji: '💄'},{value: 'refactor',name: 'refactor: 🔨 代码重构',emoji: '🔨'},{ value: 'perf', name: 'perf: ⚡️ 性能优化', emoji: '⚡️' },{value: 'test',name: 'test: ✅ 测试',emoji: '✅'},{value: 'build',name: 'build: 📦️ 打包构建',emoji: '📦️'},{ value: 'ci', name: 'ci: 👷 CI 配置变更', emoji: '👷' },{ value: 'revert', name: 'revert: ⏪️ 代码回退', emoji: '⏪️' },{value: 'chore',name: 'chore: 🚀 构建/工程依赖/工具',emoji: '🚀'},{ value: 'wip', name: 'wip: 🚧 正在开发中', emoji: '🚧' },{ value: 'workflow', name: 'workflow: 🎯 工作流程改进', emoji: '🎯' }],useEmoji: true,scopes: [],customScopesAlign: 'bottom',emptyScopesAlias: 'empty',customScopesAlias: 'custom',allowBreakingChanges: ['feat', 'fix'],skipQuestions: ['scope', 'body', 'breaking', 'footerPrefix', 'footer'] // 自定义选择指定的问题不显示}};
- 注释版本 -
commitlint.config.cjs
// @see: https://cz-git.qbenben.com/zh/guideconst fs = require('fs');const path = require('path');const scopes = fs.readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name.replace(/s$/, ''));/** @type {import('cz-git').UserConfig} */module.exports = {ignores: [(commit) => commit.includes('init')],extends: ['@commitlint/config-conventional'],rules: {// @see: https://commitlint.js.org/#/reference-rules'body-leading-blank': [2, 'always'], // 正文以空行开头'footer-leading-blank': [1, 'always'], // 脚注以空行开头'header-max-length': [2, 'always', 108], // 头部最大长度'subject-empty': [2, 'never'], // 主题不能为空'type-empty': [2, 'never'], // 类型不能为空'subject-case': [0], // 主题格式'type-enum': [2,'always',['fix','docs','style','refactor','perf','test','build','ci','chore','revert','wip','workflow','types','release']]},prompt: {messages: {type: '选择你要提交的类型 :',scope: '选择一个提交范围[可选]:',customScope: '请输入自定义的提交范围 :',subject: '填写简短精炼的变更描述 :\n',body: '填写更加详细的变更描述[可选]。使用 "|" 换行 :\n',breaking: '列举非兼容性重大的变更[可选]。使用 "|" 换行 :\n',footerPrefixsSelect: '选择关联issue前缀[可选]:',customFooterPrefixs: '输入自定义issue前缀 :',footer: '列举关联issue [可选] 例如: #31, #I3244 :\n',confirmCommit: '是否提交或修改commit ?'},types: [{ value: 'feat', name: 'feat: ✨ 新增功能', emoji: '✨' },{ value: 'fix', name: 'fix: 🐛 修复缺陷', emoji: '🐛' },{ value: 'docs', name: 'docs: 📝 文档变更', emoji: '📝' },{value: 'style',name: 'style: 💄 代码格式',emoji: '💄'},{value: 'refactor',name: 'refactor: 🔨 代码重构',emoji: '🔨'},{ value: 'perf', name: 'perf: ⚡️ 性能优化', emoji: '⚡️' },{value: 'test',name: 'test: ✅ 测试',emoji: '✅'},{value: 'build',name: 'build: 📦️ 打包构建',emoji: '📦️'},{ value: 'ci', name: 'ci: 👷 CI 配置变更', emoji: '👷' },{ value: 'revert', name: 'revert: ⏪️ 代码回退', emoji: '⏪️' },{value: 'chore',name: 'chore: 🚀 构建/工程依赖/工具',emoji: '🚀'},{ value: 'wip', name: 'wip: 🚧 正在开发中', emoji: '🚧' },{ value: 'workflow', name: 'workflow: 🎯 工作流程改进', emoji: '🎯' },{ value: 'types', name: 'types: 🏡 类型定义文件修改', emoji: '🏡' }],useEmoji: true, // 是否开启 commit message 带有 Emoji 字符。emojiAlign: 'center', // 设置 Emoji 字符 的 位于头部位置themeColorCode: '', // 设置提示查询器主题颜色, cyan青色scopes: [...scopes], // 自定义选择 模块范围 命令行显示信息allowCustomScopes: true, // 是否在选择 模块范围 显示自定义选项(custom)allowEmptyScopes: true, // 是否在选择 模块范围 显示为空选项(empty)customScopesAlign: 'bottom', // 设置 选择范围 中 为空选项(empty) 和 自定义选项(custom) 的 位置customScopesAlias: 'custom', // 自定义 选择范围 中 自定义选项(custom) 在命令行中显示的 名称emptyScopesAlias: 'empty', // 自定义 选择范围 中 为空选项(empty) 在命令行中显示的 名称upperCaseSubject: false, // 是否自动将简短描述(subject)第一个字符进行大写处理markBreakingChangeMode: false, // 添加额外的问题重大变更(BREAKING CHANGES)提问,询问是否需要添加 "!" 标识于allowBreakingChanges: ['feat', 'fix'], // 允许出现 重大变更(BREAKING CHANGES)的特定 typebreaklineNumber: 100, // 详细描述(body)和重大变更(BREAKING CHANGES)中根据字符超过该数值自动换行breaklineChar: '|', // 详细描述(body)和重大变更(BREAKING CHANGES)中换行字符skipQuestions: ['scope', 'body', 'breaking', 'footerPrefix', 'footer'], // 自定义选择指定的问题不显示// 自定义选择issue前缀issuePrefixs: [// 如果使用 gitee 作为开发管理{ value: 'link', name: 'link: 链接 ISSUES 进行中' },{ value: 'closed', name: 'closed: 标记 ISSUES 已完成' }],customIssuePrefixsAlign: 'top', // 设置 选择 issue 前缀 中 跳过选项(skip) 和 自定义选项(custom) 的 位置emptyIssuePrefixsAlias: 'skip', // 自定义 选择 issue 前缀 中 跳过选项(skip) 在命令行中显示的 名称customIssuePrefixsAlias: 'custom', // 自定义 选择 issue 前缀 中 自定义选项(custom) 在命令行中显示的 名称allowCustomIssuePrefixs: true, // 是否在选择 ISSUE 前缀 显示自定义选项(custom)allowEmptyIssuePrefixs: true, // 是否在选择 ISSUE 前缀 显示为跳过选项(skip)confirmColorize: true, // 确定提交中模板 commit message 是否着色// maxHeaderLength: Infinity, // 定义commit message中的 header 长度, 给予在命令行中的校验信息// maxSubjectLength: Infinity, // 定义commit message中的 subject 长度, 给予在命令行中的校验信息minSubjectLength: 0, // 定义commit message中的 subject 长度, 给予在命令行中的校验信息scopeOverrides: undefined, // 自定义选择了特定类型后 覆盖模块范围 命令行显示信息defaultBody: '', // 在 详细描述 中是否使用显示默认值defaultIssues: '', // 在 输入ISSUE 中是否使用显示默认值defaultScope: '', // 如果 defaultScope 与在选择范围列表项中的 value 相匹配就会进行星标置顶操作。defaultSubject: '' // 在 简短描述 中是否使用显示默认值}};
husky & lint-staged
- 安装依赖
pnpm add husky lint-staged -D
- 使用的版本
"devDependencies": {"husky": "^9.1.6","lint-staged": "^15.2.10"},
- 更新
package.json
"scripts": {"prepare": "husky",},
- 添加文件
.lintstagedrc
{"*.{js,jsx,ts,tsx}": ["pnpm run lint:fix"],"*.{css,scss}": ["pnpm run stylelint:fix","git add"]}
- 或者
lint-staged.config.cjs
module.exports = {"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": ["prettier --write--parser json"],"package.json": ["prettier --write"],"*.vue": ["eslint --fix", "prettier --write", "stylelint --fix"],"*.{scss,less,styl,html}": ["stylelint --fix", "prettier --write"],"*.md": ["prettier --write"]};
