登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  软件教程

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。

Lefthook 配置入口说明图,展示 pre-commit、jobs、run 和 glob 字段
图1:配置入口说明图,展示同一个 pre-commit 中按文件类型拆分 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 显示跳过或不执行。这里的界面说明图用于帮助理解状态层级,不代表某一次本机运行结果。

Lefthook 暂存文件检查结果说明图,展示执行与无匹配跳过状态
图2:结果状态说明图,展示匹配的 job 执行、无匹配的 job 跳过,以及“仅处理 staged files”的范围;这是原创界面说明图,不是运行截图。

不生效时按三层排查

  1. 先看依赖:确认 npm run lint 和 npx markdownlint 在当前项目环境中可用。Lefthook 只负责调度,不会替你安装检查器。
  2. 再看配置层级:确认 glob 与 run 属于同一个 job,缩进没有把它们放到 pre-commit 或另一个 job 下。
  3. 最后看文件范围:确认文件已经 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 后,无匹配文件会自然跳过,配置、输出和回退路径也更容易维护。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>