“代码规范工具集合”这个项目,我第一反应是:这可能是很多团队都在做、但很少做“全”的事情。项目标题很有概括性,背后其实是一整套工程化基建。它的目标不是简单装个ESLint,而是把规范从代码生成、提交、合并到发布的整个生命周期都管起来。这套东西能解决什么问题?最直接的答案是:让代码评审不再纠结空行和缩进,让人工审查专注在逻辑缺陷和架构设计上。适合的对象也不仅限于前端团队,任何有协作开发、代码评审、版本管理需求的研发团队,都可以从这套组合里找到能直接落地的方案。
我擅长的方向偏前端工程化,所以下面的内容会以前端技术栈(React/Vue + TypeScript为主)作为主轴来展开,但你会发现,这套工具链的底层思路是通用的。即使你在写Python、Go或者Java,核心的设计逻辑也可以平移。
1. 内容整体设计与思路拆解
1.1 为什么“单点工具”挡不住乱象
很多团队不是没有规范工具,而是工具的“孤岛化”太严重了。写代码的时候有ESLint管着,但提交代码的时候没人管,源头上一漏,坏味道就顺着代码流进主干。传统的做法里,开发者在本地跑一遍lint,觉得自己代码没问题就push了,可实际上:
- 本地跑lint的结果依赖开发者的自觉,忙起来或者项目紧急的时候,这一步是被默认跳过的。
- 规范工具之间的覆盖范围是重叠且有冲突的。ESLint管代码质量,Prettier管代码格式,两个工具同时对一个文件做“修正”时,如果不配置清楚,就会出现一边改一边又被改回去的死循环。
- 没有统一版本锁定的规范工具,不同开发者的本地依赖版本都可能不一样,最后的结果是“在我机器上是过的”。
我这次落地这个项目的时候,思路很明确:把“代码规范工具”升级成一套“多阶段防线”。不是靠一个工具,而是靠一条流水线,把规范检查嵌入到代码产生的每一个关键节点里。这也是标题里“集合”这个词的真正含义——不是堆砌,是做编排。
1.2 方案选型的核心逻辑:锁定“职责边界”
在选工具之前,必须先分清每个工具的职责是什么。职责不清晰,工具越多越乱。
我的选型逻辑是分层管理:
- 代码可读性(格式层面)用格式化工具兜底,这个交给Prettier。它可以统一所有人的缩进、单双引号、分号、换行风格。
- 代码正确性(语法层面)用Linter拦截,这个交给ESLint。ESLint负责找出代码中未使用变量、隐含类型转换、可疑的逻辑分支等问题。
- 代码提交规范(提交信息层面)用Commitlint控制格式。一个规范的提交记录,直接决定了之后生成Changelog和做版本回溯的效率。
- 代码库卫生(暂存区控制层面)用lint-staged做“提交前体检”。只检查当前的修改,不用把整个项目的历史债都翻出来。
选这些工具而不是同一类里的其他方案,我主要考虑的是生态与兼容性。ESLint目前已经是JavaScript Lint的事实标准,Prettier在格式化领域也是社区共识。commitlint则以“格式校验+规则可配”著称,能和Husky的钩子机制无缝集成。这四个工具之间各有明确边界,互补而非重叠,组合起来就不会出现“一个萝卜踩三个坑”的混乱局面。
1.3 这套方案实际上改变的是什么
我觉得很多人低估了规范工具的“行为改造”能力。它不只是改了代码的格式,而是在改变团队的协作节奏。
举个很常见的场景:没有这套工具时,新人提交PR,老手在Review里花大量时间说“这里怎么用了双引号,项目里统一单引号”“这个方法名不直观,换个动词开头吧”“ESLint报错了,你本地怎么没跑出来”。这些反馈每一条都有道理,但却把Review的焦点严重带偏了。
有了这套“集合”之后,Reviewer看到的是一个已经被机器清理过的、风格统一的Diffs,可以直接切入逻辑层面的问题。这个转变,对一个研发团队的效率提升是相当可观的。这也是为什么我建议不止前端团队做,整个研发组织都可以参考这套设计——工具不同,逻辑一样。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节解析与实操要点
2.1 ESLint:不只是“查错”,更是“规则可编程”
很多人用完ESLint的评价是“挺好用的,帮我把代码改对了”,但这样理解ESLint就有点浪费了。ESLint真正的价值在于“规则可编程”。
它内置的规则叫core rules,大概有两百多条,覆盖了可能的语法错误、代码气味、最佳实践等。但内置规则只是起点,ESLint的插件机制才是它的真正王牌。你可以在项目里通过extends字段把eslint:recommended、plugin:@typescript-eslint/recommended、plugin:react/recommended等内容放进来。这种“叠Buff”的玩法,让它可以轻松适配不同技术栈。
我在配置ESLint时倾向于“严格但不苛刻”的策略。严格的意思是:语法层面的错误、明显的bug、未定义变量、重复引用等必须报错。不苛刻的意思是:对于代码风格层面的偏好,比如是否强制使用const而不是let,这些交给Prettier去管,不要和ESLint的重叠。
重点是留意版本匹配问题,ESLint 8和ESLint 9在配置文件写法上差异比较大。ESLint 9之后已经默认使用新版的扁平化配置(flat config),旧的.eslintrc模式被标记为弃用。如果你正在新建项目,直接上扁平化配置;如果是老项目升级,就必须注意迁移方案,避免配置失效导致Lint规则完全不生效。
2.2 Prettier:代码格式的“一刀切”哲学
Prettier的设计理念跟ESLint完全不同。ESLint在判断代码风格时给你留了很多自定义空间,而Prettier的哲学是“你最好别配置,让我来替你决定”。这也是它一个被吐槽的点:开发者觉得它太“专断”,但我的经验是——专断恰恰是好事。
如果格式化工具的规则完全开放,团队里每个人都可以用不同风格格式化同一份文件,diff就永远干净不了。Prettier用最少的选项(tab宽度、分号、单引号、行尾等)约束全局,统一度最高。它主动牺牲了“可配置性”来换取“一致性”,这个取舍我认为是合理的。
Prettier接入时最大的坑是:不管是ESLint还是Stylelint,都建议把和格式相关的规则关掉,避免冲突。有两个工具可以配合做这件事——eslint-config-prettier负责把ESLint中和Prettier重叠的格式规则关掉;@trivago/prettier-plugin-sort-imports或@ianvs/prettier-plugin-sort-imports负责在格式化时顺便整理import顺序,这个体验提升非常明显。
2.3 Commitlint:小提交信息里的大学问
Commitlint可能在这个“集合”里看起来最不起眼,但它的长期收益反而是最高的。为什么?因为一份规范的提交信息就是项目历史的索引。
项目进过新人、做过大重构之后,git log基本就是一团乱麻,没人敢碰历史。而如果从第一天起就约束提交信息格式(比如采用社区最通用的type(scope): subject结构),整个提交历史就会变成一张清晰的路线图:
code复制feat(button): add new primary variant
fix(button): resolve hover state bug
docs(readme): update api usage example
refactor(utils): extract date formatter
commitlint本身并不限制格式,它靠的是正则表达式和一组约定式规则(conventional commits spec)。你需要定义它允许的type枚举、subject是否必须非空、header最大长度等。配合Husky的commit-msg钩子,开发者提交信息一不合规,直接本地拦截,错误提示清晰明了。这套机制带来的直接价值是:release过程中可以通过读取提交历史自动生成changelog,版本回溯时也能秒级定位到具体改动。
2.4 Husky与lint-staged:把防线前移到提交前
如果只有前面的工具没有Husky和lint-staged,整套方案还缺最关键的一环——自动化关卡。
Husky负责在Git的各个阶段装入钩子,典型的就是pre-commit和commit-msg。pre-commit钩子在执行git commit前触发,commit-msg钩子则专门负责检查提交信息格式。两者配合,就把“代码规范”嵌进了版本控制的关卡里。
但这里有个极其容易踩的坑:如果没有lint-staged,直接在全量项目上跑ESLint和Prettier,那大项目的pre-commit钩子会变得奇慢无比,因为每次提交都要lint整个仓库。lint-staged恰好解决了这个问题——它只针对git add进入暂存区的文件执行lint或格式化,不是所有文件。把lint-staged配置成“对暂存区的js/jsx/ts/tsx文件运行eslint --fix,对json/md/yaml运行prettier --write”,几分钟内就能让全团队的提交速度稳定在可接受的范围。
这个组合可以说是工程化规范里性价比最高的一笔投入。因为它把“发现代码问题”的时间点,从“代码Review/CI阶段”提前到了“开发者本地执行commit命令的瞬间”。发现问题越早,修复成本越低,这是放之四海而皆准的工程原则。
3. 实操过程与核心环节实现
3.1 初始化与依赖安装:版本锁定是第一优先级
第一步就是在项目里初始化一套标准的工程化环境。我建议在一个全新的git仓库中操作,避免历史垃圾影响验证结果。
bash复制# 初始化package.json
npm init -y
# 安装核心依赖
npm install --save-dev eslint @eslint/js typescript typescript-eslint
npm install --save-dev prettier eslint-config-prettier
npm install --save-dev husky lint-staged @commitlint/cli @commitlint/config-conventional
说明一下这几个依赖的用途:
@eslint/js是ESLint 9时代的基础配置包,提供recommended规则集。typescript-eslint是让ESLint能识别TypeScript语法并应用类型感知规则的核心插件,绝不是可选项。eslint-config-prettier用于关闭ESLint内部与Prettier重复的格式规则。@commitlint/config-conventional是一套commit message规范预设,对应Angular风格的type(scope): subject格式。
版本号这东西,我建议一定要在package.json里锁定下来。团队里如果有人用npm install自动升级了小版本,可能就会遇到插件和核心工具之间compat break,问题还特别难排查。我习惯把依赖写成精确版本,不加^,或者用package-lock.json做统一锁定。
3.2 ESLint扁平化配置:新版写法和参数解释
现在来说ESLint 9的扁平化配置。在项目根目录创建eslint.config.js:
javascript复制import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import prettierConfig from 'eslint-config-prettier';
export default [
{
ignores: ['dist/**', 'node_modules/**', 'coverage/**'],
},
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parser: tseslint.parser,
},
rules: {
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],
},
},
prettierConfig,
];
这里几个关键参数值得展开:
argsIgnorePattern和varsIgnorePattern设为^_的作用是允许开发者用下划线开头的变量名来表示“我故意不用的”,比如某些回调参数必须声明但又不使用,这种情况下不报错很实用。consistent-type-imports配合prefer: 'type-imports'的作用,是强制你从import { SomeType } from './types'改成import type { SomeType } from './types'。这个看起来不起眼的改动,在开启isolatedModules的Vite项目里能显著减少编译期问题。
eslint-config-prettier一定要放到最后。它的本质是“把所有可能和Prettier冲突的规则关掉”,所以如果后面还有其他规则覆盖它,那冲突就白关了。这个顺序问题我在老项目里踩过坑,新项目从一开始就放到最后即可。
3.3 Prettier配置与忽略文件:少即是多
Prettier的配置文件我用.prettierrc.json:
json复制{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf"
}
这些参数不多,但每一条背后都有应用场景:
printWidth是单行最大长度,我设100而不是默认80,是因为现代前端代码的组件名、函数签名经常很长,80太容易换行,导致嵌套代码的可读性下降。semi和singleQuote是国内前端团队最常见的偏好,如果你团队没有特殊执念,直接跟随这个默认即可。trailingComma: 'all'意味着多行结构里每个元素后面带逗号,这能大幅降低后续增删行时产生的diff噪音。endOfLine: 'lf'必须设置,否则跨平台开发时Windows的CRLF和Mac/Linux的LF会在git diff里产生大量无意义的行尾变更。- 还有一句需要记住:不要和ESLint抢声明式格式规则的活,冲突了就用
eslint-config-prettier关掉ESLint的格式规则。
然后建一个.prettierignore:
code复制node_modules
dist
coverage
package-lock.json
pnpm-lock.yaml
yarn.lock
格式化的意义是让“源码”可读,而不是让“构建产物”可读。忽略掉这些目录能节省大量格式化时间,锁文件这种自动生成的结构更是没有必要让Prettier介入。
3.4 Husky自动化钩子:从“提醒”到“强制”
这个环节要小心,因为Husky的安装在npm 7以上的版本里默认会自动执行prepare脚本,但如果你是用npm install --save-dev husky装的,有时候不会自动初始化。稳妥的手动步骤是:
bash复制# 初始化husky,生成.husky目录
npx husky init
# 添加pre-commit钩子
npx husky add .husky/pre-commit "npx lint-staged"
# 添加commit-msg钩子(注意:需要先创建好commitlint配置)
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"
pre-commit钩子里的npx lint-staged会读取lint-staged配置,对暂存区文件做检查。commit-msg钩子里的$1是git传给钩子的提交信息文件名,commitlint会读取该文件内容并做校验,不通过则commit失败。
lint-staged这部分我建议配置在package.json里,因为它和构建脚本放在一起更直观,便于团队新成员一眼看到全貌:
json复制{
"lint-staged": {
"*.{ts,tsx,js,jsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,yaml,yml}": ["prettier --write"]
}
}
这里有个细节值得注意:对*.{ts,tsx}文件先跑eslint --fix再跑prettier --write,两个命令都会修改文件,之后git add的暂存区内容才是最终版。顺序也不能反,如果先跑Prettier再跑ESLint,ESLint的auto fix可能会改变Prettier刚格式化的代码,导致两个工具之间互相推翻。这个“先lint后format”的次序是我实践下来比较稳的顺序。
3.5 commitlint配置与解析规则
创建commitlint.config.cjs:
javascript复制module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'build', 'ci', 'chore', 'revert'],
],
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
'header-max-length': [2, 'always', 100],
},
};
这里type-enum就是限制type的类型值列表,常用的就那么几种,自己定制时不要写太多花哨类型,避免团队里每个人都定义一种type,那就失去一致性了。
subject-case设置为sentence-case等不通过,是要求提交信息主体不要以大写字母开头、不要用类似标题的写法,这样日志风格能保持统一。header-max-length设100,避免有人把一整篇PR描述塞进提交信息第一行。header的长度控制很关键,因为它影响后面工具渲染changelog的排版。
注意:commitlint配置文件默认支持.cjs后缀。如果你的项目是package.json里没有写"type": "module",用CommonJS写module.exports没问题。但如果项目已经设置成ESM项目,commitlint.config.js可能会被当作ESM加载,这时候就要小心,要么把后缀改成.cjs,要么就在文件里用export default。
3.6 全链路压测:从“写代码”到“提交成功”的一次完整演练
工具都配置好了,得做一次全链路验证,不能装完就认为万事大吉。
我习惯的验证流程是这样:
第一步,写一段“故意不规范”的代码。比如在src/index.ts里写:
typescript复制const unusedVar='hello'
console.log ( 'world' )
export const add=(a:number,b:number)=> {return a+b}
这里的核心问题是:有个未使用的变量unusedVar,console.log和函数参数间多了空格,字符串用了单引号但分号缺失。
第二步,执行git add .提交暂存,然后git commit -m "test"。此时pre-commit钩子自动触发,lint-staged读取暂存区的index.ts文件,依次执行eslint --fix和prettier --write。预期结果是ESLint报错no-unused-vars,pre-commit直接拦截,commit失败。这里的拦截是好事,说明防线生效了。
第三步,把代码里未使用的变量删掉,重新git add,再次git commit -m "test"。这次预期是pre-commit通过,但commit-msg钩子会拦截,因为test这个type不在type-enum允许的feat、fix这些范围里。错误提示应该会列出合法的type列表。
第四步,改成git commit -m "chore: validate toolchain setup",这次两边都应该通过。提交成功之后,git log -1能看到格式规范的提交信息,并且观察刚才被格式化的代码——它们已经被--fix自动修正了。
这套流程验证完成后,基本上就敢把工具链推给团队了。很多配置看起来合理,但走一遍真实提交链路才发现问题,比如Husky钩子里的命令路径不对、lint-staged匹配不到文件、ESLint配置里import语法不兼容等。这些都是必须在“发布给全员”之前先踩平的。
4. 常见问题与排查技巧实录
我接触到的团队在落地这套工具链时,遇到的问题翻来覆去就那几类。这里整理成一份速查表,你可以直接抄作业:
| 常见问题 | 典型现象 | 排查思路与解决方案 |
|---|---|---|
| ESLint和Prettier互相打架 | 保存一次代码,格式化后ESLint又报格式错误 | 确认eslint-config-prettier放在ESLint配置数组的最后,用它关闭重复规则;检查ESLint规则里是否单独开启了indent、quotes等格式类规则,有就删掉 |
| pre-commit钩子不生效 | 开发者提交时绕过了Husky,或提示husky命令不存在 |
检查项目根目录是否存在.husky目录,确认prepare脚本是否存在:"prepare": "husky";确认git版本 >= 2.9;.husky/pre-commit文件是否有执行权限 |
| lint-staged不匹配文件 | 暂存了.tsx文件但钩子没跑 |
检查配置里的glob表达式是否写错,比如*.{ts,tsx}和**/*.{ts,tsx}的区别;确认暂存文件路径是相对的 |
| commit-msg校验绕过 | 有人用--no-verify提交了不规范的commit message |
这属于流程执行问题,工具之外要靠Code Review和CI双保险;CI里跑commitlint,防止--no-verify绕过本地钩子 |
| 格式化后文件巨大diff | 初次接入时全项目格式化产生海量变更 | 先新增.prettierignore排除旧代码,然后分模块逐步格式化;立刻全量格式化会淹没真实逻辑变更,Review难度激增 |
| ESLint版本升级后配置报错 | ESLint 9迁移后旧的.eslintrc不识别 |
换成新版的eslint.config.js;把parserOptions迁移到languageOptions;使用@eslint/js提供的configs.recommended |
4.1 关于“格式化大型历史项目”的独特经验
这里说一个我特有的经验:如果团队要在一个大存量项目上引入Prettier,不要急着一把梭哈全量格式化。推荐的路径是:
先只把新增/修改的文件交给Prettier,通过lint-staged在提交时对新代码格式化,旧文件不动。等到某个模块有重构计划时,再把那个模块的历史文件一起格式化。这样生成的diff是可控的,Reviewer不会因为几万个格式化diff而崩溃。
4.2 一个非常隐蔽的配置坑:commitlint需要读取绝对路径参数
还有一次我们在CI里跑commitlint时,命令一直报“不能读取commit message文件”。排查了半天,才发现是CI环境在clone仓库时用了--depth=1,导致git log看不到历史,而commitlint --edit "$CI_COMMIT_SHA"要求读取的是当前提交的message文件。后来改成配合git show -s --format=%B的方式,把消息内容喂给commitlint stdin,才彻底解决。
在本地开发里,commit-msg钩子用的是--edit $1,这里$1是git生成的.git/COMMIT_EDITMSG文件路径,属于绝对路径,所以不会出问题。但如果在自定义脚本里直接调用commitlint就要注意路径解析方式。
4.3 配置了还不生效?先检查eslint.flatConfig还是legacy
ESLint 9默认用扁平化配置,但如果你项目里存在.eslintrc文件,ESLint有时会不读取新的eslint.config.js,或者出现“找不到配置文件”的报错。我的建议是:直接删掉.eslintrc,不要保留两套配置。
另外有个容易忽略的细节:ESLint 9扁平化配置会忽略.eslintignore文件,忽略逻辑统一放在eslint.config.js的ignores字段里。如果你从旧版本升级,一定要把.eslintignore里的内容迁移到新配置里。这个“不生效但不报错”的问题,排查起来最费时间,因为工具不会给你任何警告。
5. 工具链扩展与团队落地的进阶建议
5.1 加入Stylelint:让CSS/SCSS也进入规范体系
如果你团队写React或Vue项目,样式文件也是代码的一部分,完全可以在同一套工具链里加入Stylelint。这一点在标题的“集合”语境里很值得展开。
bash复制npm install --save-dev stylelint stylelint-config-standard-scss @stylistic/stylelint-plugin
配置stylelint.config.cjs:
javascript复制module.exports = {
extends: ['stylelint-config-standard-scss'],
plugins: ['@stylistic/stylelint-plugin'],
rules: {
'color-hex-length': 'short',
'declaration-block-no-duplicate-properties': true,
'selector-class-pattern': '^[a-z][a-zA-Z0-9]*$',
},
};
color-hex-length强制颜色值用短十六进制(#fff而不是#ffffff),selector-class-pattern强制class命名使用小驼峰或统一风格。Stylelint的作用和ESLint完全类似,只是对象从JavaScript变成了样式文件。把它加入lint-staged的匹配规则里,样式问题也会在提交前被拦截。
5.2 编辑器配置:让规范“主动找上门”
配置工具链只是第一环,如果不接入编辑器的保存自动修复,开发者光靠CLI提示来修代码,体验很割裂。所以优秀的规范工具集合一定包含了.vscode/settings.json的配置:
json复制{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
关键语义是:保存时先执行“修复所有可自动修复的ESLint问题”,然后再触发Prettier格式化。这个顺序和lint-staged里的“先eslint后prettier”保持了一致。配合这部分配置后,“规范”就从“偶尔在CI里报个红”变成了“打代码的每一秒都在悄悄被纠正”。
5.3 团队推广:比工具更重要的是“第一次死亡体验”
工具本身是死的东西,关键是让团队愿意“被管”。
我的经验是:不做长篇大论的宣讲,直接让全员体验一次“工具拦截自己的不合规提交”。比如在项目里故意留一个明显的代码风格问题,让一个同学去提交,他看到终端里红色报错信息的那一刻,比你在会议上讲十页PPT都有效。等他改完再提交成功后,他会从“被动遵守”变成“主动理解”:原来工具是帮我省事,不是找茬。
整个团队的接入节奏可以参考“三阶段法”:
- 第一阶段(一周内):试点成员在有代表性的模块接入并跑通,收集配置问题。
- 第二阶段(两周内):全项目接入,旧代码先不强制格式化,只规范新代码。
- 第三阶段(一个月后):对存量代码做分批格式化,并在CI中开启验证,形成强制约束。
5.4 规范工具集与CI/CD的联动:把防线延伸到远端
本地Husky钩子可以被--no-verify跳过,这无法根治。所以要确保远端CI/CD流水线上也有一道相同的校验。典型做法是在CI的lint job中运行:
bash复制npx eslint .
npx prettier --check .
npx commitlint --from HEAD~1 --to HEAD --verbose
prettier --check .不是修改文件,而是只检测当前代码是否已经符合格式化要求。这意味着即使本地有人用--no-verify跳过了钩子,远端CI依然会挡住问题代码。把规范校验变成CI的必过门禁,比任何代码评审纪律都更可靠,因为机器不会讲情面。
6. 实操心得与最后的提醒
工具配置文档网上非常多,但真正影响这套工具链成功与否的,往往不是那些配置项,而是团队的使用习惯。
我的体会是:代码规范工具集合的核心不是“选最流行的工具”,而是“用最稳定的链路把规范动作串起来”。ESLint、Prettier、commitlint、Husky、lint-staged这个组合,能覆盖的链路已经相当完整——从代码编写时的编辑器辅助,到提交前的自动化修复,再到提交信息的格式校验,最后是CI/CD的远端兜底。每一层都是前面防线的补充,而不是替代。
最后再分享一个小技巧:如果你在一个新项目里想快速验证这套工具链是否真的可以“直接抄作业”,我建议你把上面所有的配置项复制到一个临时目录,然后完整跑一遍git init、npm install、git add .、git commit的流程,看它在真实提交时拦截了哪些东西。这个过程不仅让你确认配置无误,还会帮你熟悉工具给出的错误提示长什么样——以后团队成员在群里问“为什么提交被拒绝了”时,你可以直接告诉他去看哪一行提示。
工具链本身不是目的,让团队里的每个人都少在无意义的格式争论上消耗精力,才是这套东西真正值得投入的原因。
