Lefthook 怎么只对暂存文件运行不同的检查命令
来源:17golang原创
时间:2026-11-05 12:40:51 302浏览 收藏
如果一个项目同时有前端代码和 Markdown 文档,pre-commit 不应该让两套检查命令互相抢文件。Lefthook 的做法是:每个 job 都把 {staged_files} 作为输入,再用 glob 限定它能看到的暂存文件。没有匹配文件时,这个 job 会被跳过。
官方地址:https://github.com/evilmartians/lefthook
把“暂存文件列表”和“文件类型过滤”同时写在 job 上,就能让同一个 pre-commit 按扩展名运行不同命令,而不会检查未暂存的工作区文件。
先确认 Lefthook 的配置入口
在项目根目录找到 lefthook.yml,沿着“pre-commit → jobs → job → run/glob”这一层级编辑。这里的重点不是新增一个全局脚本,而是把每一类文件的规则拆成独立 job。

用 staged_files 绑定本次提交内容
{staged_files} 是关键占位符。它代表本次提交已经放入暂存区的文件集合,适合直接传给 lint、格式化或文档检查命令。若改用固定目录或工作区扫描命令,检查器就可能把没有准备提交的文件也纳入结果,排错时很难判断是哪一批文件触发了失败。
# lefthook.yml:让两个 job 都只接收本次提交的暂存文件
pre-commit:
parallel: true
jobs:
- name: 前端文件检查
run: npm run lint -- {staged_files}
- name: Markdown 文档检查
run: npx markdownlint {staged_files}
这段配置先表达“输入范围”,还没有表达“文件类型”。下一步给每个 job 加上自己的 glob,这样前端检查不会收到 Markdown,文档检查也不会收到 TypeScript。
用 glob 给不同暂存文件分配命令
把 glob 写在对应 job 上。Lefthook 会对 pre-commit 的暂存文件进行过滤,并把过滤后的结果填入同一 job 的 {staged_files}。下面是一个可直接改造的最小配置:
# lefthook.yml:不同扩展名使用不同检查命令
pre-commit:
parallel: true
jobs:
- name: 前端检查
glob: "*.{js,ts,jsx,tsx}"
run: npm run lint -- {staged_files}
- name: 文档检查
glob: "*.md"
run: npx markdownlint {staged_files}
例如本次暂存了 src/app.ts 和 docs/guide.md,两个 job 都会各自得到匹配的文件;如果只暂存 docs/guide.md,前端 job 没有匹配项,就会跳过,文档 job 才负责检查。
嵌套目录和 glob 的两个边界
第一,glob 仍然以 Git 仓库的实际根目录计算,job 的 root 不会改变 glob 的计算起点。第二,文档里的 ** 默认匹配一层或更多层目录,不等于“零层或更多层”。如果既要匹配仓库根目录文件,又要匹配子目录文件,可以拆成两个模式,或者根据项目需要启用 glob_matcher: doublestar。
# lefthook.yml:同时覆盖根目录和 docs 子目录的 Markdown
pre-commit:
jobs:
- name: 文档检查
glob:
- "*.md"
- "docs/**/*.md"
run: npx markdownlint {staged_files}
不要一开始就把所有文件交给一个命令再在脚本里二次判断。拆成多个 job 后,状态输出会直接告诉你哪条规则执行、哪条规则因无匹配文件跳过。
安装钩子并确认保存状态
配置保存后,在项目目录执行安装命令,让 Git 钩子重新读取当前配置:
# 在项目根目录重新生成 Lefthook 的 Git 钩子
lefthook install
# 只暂存前端文件时,预期看到前端检查执行、文档检查跳过
git add src/app.ts
git commit -m "更新前端代码"
确认点有三个:命令行输出中的 job 名称与配置一致;命令参数只出现本次暂存的文件;没有匹配文件的 job 显示跳过或不执行。这里的界面说明图用于帮助理解状态层级,不代表某一次本机运行结果。

不生效时按三层排查
- 先看依赖:确认
npm run lint和npx markdownlint在当前项目环境中可用。Lefthook 只负责调度,不会替你安装检查器。 - 再看配置层级:确认
glob与run属于同一个 job,缩进没有把它们放到pre-commit或另一个 job 下。 - 最后看文件范围:确认文件已经
git add,扩展名符合 glob;如果没有匹配项,job 被跳过是正常行为,不是命令失败。
如果暂时不想让某一类检查参与提交,可以先从 jobs 中移除对应项或缩小它的 glob 范围,再重新执行 lefthook install。保留最小配置比把所有判断塞进一个脚本更容易回退。
常见问题
Lefthook 的 glob 不写 {staged_files} 也能过滤吗?
在 pre-commit 中,如果 job 配置了 glob 但 run 没有文件模板,Lefthook 仍会尝试对暂存文件应用过滤;不过显式写出 {staged_files} 更直观,也能让检查命令明确接收哪些文件。
为什么检查命令收到的文件比预期少?
通常是 glob 与 Git 仓库根目录的相对路径不一致,或文件尚未进入暂存区。先用实际相对路径调整模式,不要只修改命令名称。
可以让两个 job 串行运行吗?
可以去掉 parallel: true,让 job 按配置顺序运行。是否并行取决于检查器是否会写同一文件,以及团队是否需要稳定的输出顺序。
总结
Lefthook 分流暂存文件只需要抓住两点:命令参数使用 {staged_files},文件范围使用 job 级别的 glob。每个文件类型独立成 job 后,无匹配文件会自然跳过,配置、输出和回退路径也更容易维护。
-
146 收藏
-
474 收藏
-
358 收藏
-
381 收藏
-
158 收藏
-
498 收藏
-
186 收藏
-
327 收藏
-
249 收藏
-
463 收藏
-
144 收藏
-
416 收藏
-
326 收藏
-
145 收藏
-
227 收藏
-
309 收藏
-
488 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习