当前位置:首页 > 文章列表 > 文章 > 软件教程 > Lefthook 配置在 monorepo 中怎么让子项目复用根目录钩子

Lefthook 配置在 monorepo 中怎么让子项目复用根目录钩子

来源:17golang原创 2026-11-05 12:43:39 0浏览 收藏

在 monorepo 里,Git 仓库只有一个根目录,但 frontend、backend、tools 往往各自有 package.json、Gemfile 或独立的检查命令。Lefthook 的稳定做法是:把 Git 钩子安装在仓库根目录,根配置用 extends 汇总子项目配置,再给每个子项目任务设置自己的 root 和文件匹配规则。这样提交入口只有一套,命令却不会跑错目录。

官方地址:https://github.com/evilmartians/lefthook

不要在每个子目录重复安装 Lefthook。根目录保留唯一主配置,子项目只提供可合并的任务定义;执行目录交给 root: "frontend/" 这类任务级配置,文件过滤仍然按照 Git 仓库根目录计算。

先把目录和职责分开

假设仓库结构如下,两个应用共用一次 pre-commit,但检查器不能互相读取对方的依赖目录:

monorepo/
├── lefthook.yml
├── frontend/
│   ├── package.json
│   └── src/
├── backend/
│   ├── pyproject.toml
│   └── app/
└── tools/
    └── scripts/

这里有三个容易混淆的概念:

  • lefthook.yml 是根目录的入口,负责把配置组装起来;
  • root 改变具体任务执行时的当前工作目录;
  • glob 仍从实际 Git 根目录匹配路径,不能把它理解成“先进入 root 再从零开始匹配”。

如果你把 frontend 和 backend 初始化成两个完全独立的 Git 仓库,这套方案就不再是本文讨论的范围;本文只针对一个 Git 根目录下的多个子项目。

在根目录登记唯一的 Lefthook 入口

操作路径是“项目根目录 → 新建 lefthook.yml → 写入 extends”。根配置不承担所有命令细节,只负责把子项目配置纳入同一套钩子。

# 这行注释说明配置入口只放在 Git 仓库根目录
extends:
  # 让前端任务从自己的配置文件维护
  - frontend/lefthook.yml
  # 让后端任务保持与前端相同的提交入口
  - backend/lefthook.yml

pre-commit:
  # 根层只负责统一调度,具体任务由 extends 文件提供
  parallel: true

可见状态应当是:根目录存在一个主配置,子项目文件只作为被合并的配置来源。Lefthook 官方说明中,extends 的内容会合并到主配置;如果多个任务希望在合并时被识别为同一个任务,给它们稳定的 name 会比依赖数组位置更容易维护。

根目录 Lefthook 配置通过 extends 连接 frontend 和 backend 子项目配置的界面示意
图1:根入口与子项目配置的原创操作示意图,不是截图。

在子项目文件里设置 root 和任务

操作路径是“frontend → lefthook.yml → pre-commit.jobs → 设置 root、glob、run”。下面的配置把前端与后端拆成两个命名任务,并让命令在各自目录里执行:

# frontend/lefthook.yml:命令在 frontend/ 下执行
pre-commit:
  jobs:
    - name: frontend-lint
      # 注意保留末尾斜杠,避免路径拼接出现歧义
      root: "frontend/"
      # glob 仍按 Git 根目录匹配,所以这里写 frontend 下的相对路径
      glob: "frontend/**/*.{js,ts,tsx}"
      # staged_files 会把匹配到的暂存文件交给前端脚本
      run: npm run lint -- {staged_files}

# backend/lefthook.yml:命令在 backend/ 下执行
pre-commit:
  jobs:
    - name: backend-check
      # Python 工具读取 backend/ 下的 pyproject.toml
      root: "backend/"
      # 只筛选后端源码,避免前端提交触发后端检查
      glob: "backend/**/*.py"
      # 这里使用仓库根目录传入的文件路径,命令仍在 backend/ 中启动
      run: python -m ruff check {staged_files}

这里最容易出现的误区是把 glob 写成 "src/**/*.{js,ts}"。当 Lefthook 从仓库根目录计算暂存文件时,frontend 的任务应写成 "frontend/src/**/*.{js,ts}";而命令的当前目录由 root: "frontend/" 决定。两个字段解决的是不同问题。

如果你使用的是嵌套任务组,可以把共同的 root、glob、env 或 files 放到 group 上,让组内任务继承;需要被 extends 或本地配置稳定合并的组,也应设置名称。

把钩子安装到根目录并查看合并结果

操作路径是“项目根目录 → Lefthook 命令 → install → dump”。这一步先安装一次根钩子,再查看 Lefthook 实际使用的合并配置:

# 在 monorepo 根目录执行,确保 Git 根和配置入口一致
lefthook install

# 输出 main config、extends 和 local config 合并后的实际配置
lefthook dump

# 手动运行一次提交钩子,观察哪些任务被匹配
lefthook run pre-commit

界面或命令输出里应能看到 frontend-lint 与 backend-check 两个命名任务。提交只改了 frontend/src/App.tsx 时,前端任务应保留,后端任务应因 glob 没有匹配文件而跳过;反过来修改 backend/app/main.py 也是同理。

Lefthook 合并配置后的 pre-commit 任务、root 工作目录和 glob 匹配状态界面示意
图2:合并后的钩子任务与路径匹配状态示意图,不是运行截图。

路径匹配为空时怎么判断

遇到任务显示跳过,不要先把 root 改成仓库根目录。按下面的顺序看最省时间:

  1. 先确认文件已经暂存,因为 {staged_files} 只代表当前提交候选文件。
  2. 再比较 glob 与 Git 根目录的相对路径,例如 frontend/src/index.ts 是否真的带有 frontend/ 前缀。
  3. 最后确认 root 以目录形式书写,并且命令需要的 package 或配置文件确实存在于该目录。
# 把目标文件加入暂存区,模拟一次前端提交候选
git add frontend/src/index.ts

# 只运行提交钩子,不创建提交,便于查看匹配和工作目录
lefthook run pre-commit

如果 dump 里任务存在但运行时为空,通常是文件没有暂存,或者 glob 少写了子项目目录。若任务能匹配到文件但命令报找不到 package,通常是 root 写错;此时修正执行目录,而不是扩大 glob。

常见配置误区

每个子项目都执行一次 lefthook install

在一个 Git 仓库中重复安装会让维护者误以为每个子项目都是独立入口。把安装动作固定在根目录,子项目只维护被 extends 的配置即可。

把 root 当成 glob 的起点

root 是命令工作目录和路径过滤边界,官方文档明确说明 glob 仍按 Git 仓库真实根目录计算。只要理解这一点,绝大多数“任务为什么跳过”都能直接定位。

直接复制整段 pre-commit 而不命名任务

配置拆分后,多个文件可能同时定义同一个钩子。给具体 job 或 group 写上稳定的 name,再用 dump 查看最终合并结果,后续覆盖和扩展会更可控。

最后确认这套结构是否适合你的仓库

如果你的目标是“一个 Git 仓库、一套根钩子、多个子项目各自运行检查”,推荐保留下面的最小结构:

monorepo/
├── lefthook.yml                 # 唯一入口:extends 子项目配置
├── frontend/lefthook.yml       # root: frontend/,glob: frontend/**
└── backend/lefthook.yml        # root: backend/,glob: backend/**

安装时只在根目录运行 lefthook install,排查时先运行 lefthook dump,执行目录看 root,文件范围看 glob。这四个动作能把“钩子没有触发”“命令读错配置”和“子项目互相干扰”拆成三个独立问题处理。

官方文档入口:https://lefthook.dev/configuration/

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Gitleaks 怎么用 baseline 只报告新增泄露结果Gitleaks 怎么用 baseline 只报告新增泄露结果
上一篇
Gitleaks 怎么用 baseline 只报告新增泄露结果
Lefthook 安装后 Git 提交没有触发怎么办
下一篇
Lefthook 安装后 Git 提交没有触发怎么办
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    893次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    894次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    978次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    966次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    793次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码