从commit校验失效问题探究husky原理

一、背景

之前创建的项目,发现代码 commit 提交的时候没有了任何校验,具体表现:

  • 一是 feat fix 等主题格式校验没有了
  • 二是代码 lint 不通过也能提交

尝试解决这个问题,并深入了解husky的实现原理,将相关的一些知识点分享下。

二、lint配套工具

完整的一套代码规范工具,可能包含:husky + lint-staged + eslint + stylelint + prettier

1. git 钩子:

git 本身提供多个生命周期钩子,常见的例如 pre-commit、commit-msg、pre-push 等。

pre-commit 钩子:

在 git commit 命令执行之前触发,配合指定的脚本命令可用来执行代码 lint 校验、代码格式化、跑测试用例等任务,以确保在提交代码之前达到一定的质量标准。

commit-msg 钩子:

是在 git 编辑提交信息之后、提交之前触发,可用于 commit 信息的格式校验。

2. husky:

husky 是一个用来简化 Git 钩子管理的工具。它可以帮助你在 Git 的生命周期事件(如 pre-commit、pre-push 等)中轻松地添加脚本,并且与常用的 js 工具和任务管理器(npm、yarn)集成良好。

3. lint-staged:

lint-staged 用于结合 husky 和 pre-commit,能做到只对 Git 暂存区(git add . 之后)的文件 运行校验任务,从而实现只处理改动的文件,提升commit效率,在大型项目上效果更加明显。

4. eslint:

eslint 是用于对 js 和 jsx 做代码校验的工具,通过静态分析代码来快速地发现和修复一些代码语法问题,帮助前端开发规范代码、提高效率。

5. stylelint:

stylelint 是用于对 css 样式 做代码校验的工具,同上述 eslint 类似,帮助前端开发在编写 css 及 less等预处理器代码时避免犯错,提升开发效率。

6. prettier:

prettier 是目前最常用的前端代码格式化工具,支持多项规则配置,帮助统一代码风格。适当的配置后可以与上述 eslint 和 stylelint 兼容。

三、husky原理

疑问:

  • git 是全局命令,而 husky 只是项目里引入的一个插件,它是怎么和全局的 git 命令产生联系的?
  • 我们通过 git commit -m “xxx” 提交代码时,husky 做了什么?

(以下以 mac os 下 husky v9 版本示例)

1. husky初始化:

1)配置方式:
  • 一般会在项目 package.json 的 scripts 里配置下 prepare 命令(“prepare”: “husky”),用于执行 husky 的初始化。prepare 是 npm 的钩子,在项目 npm i 时会自动执行 npm run prepare。
2)解析husky命令:
  • 执行 husky 命令 实际就是执行 node_modules/.bin/husky 文件,里面没啥东西,主要是三块,自动修改 husky init 命令、错误命令输出处理、执行 index.mjs,显然核心代码在 index.mjs 里。
  • 找到 node_modules/husky/index.mjs 文件,解析下里面的核心代码动作:
    • 执行命令 git config core.hooksPath .husky/_ ,创建目录 .husky/_
    • .husky/_ 里写入 .gitignore 内容为 *
    • 复制 node_modules/husky/husky 文件内容到 .husky/_ 的 h 文件
    • 遍历 l 数组,即支持的所有 git 钩子,复制到 .husky/_ 下同名文件,内容统一为 . “${0%/*}/h”
    • .husky/_ 里创建文件 husky.sh,内容为空。
3)解析说明:
  • 一般来说项目都是用 git 来作为代码版本控制工具,每个项目在 git init 初始化后,根目录都会生成一个 .git 隐藏文件夹,里面是 git 的配置文件 及 代码记录信息。

  • husky 在执行初始化命令后,会自动修改 git 的 hooks 目录,具体表现为在项目 .git 文件夹下的 config 文件里新增了 core.hooksPath 配置,指向项目的 .husky/_ 目录,这样执行 git commit 命令时就会自动寻找项目 .husky/_ 下的钩子文件。

    • 未指定时,默认的 hooks 目录是 .git/hooks
    • 在这里插入图片描述
  • 然后在 .husky/_ 目录下自动生成 git 钩子文件 和 一些执行脚本。
    *

2. husky执行流程:

(以项目 pre-commit 钩子为例)

1)开始运行 commit
  • 修改项目文件,运行 git add .
  • 运行 git commit -m “xxx”,开始流程。
2)读取 hooks 目录配置
  • git工具会去项目的 .git 目录 config 文件里读取 core.hooksPath 目录配置,指向了.husky/_ 目录
3)寻找 pre-commit 业务脚本
  • 首先在 .husky/_ 目录下找到 pre-commit 钩子文件,即 .husky//pre-commit,并执行,实际执行是指向了同目录下的 h 文件,即 .husky//h
    • ${0%/*}:0表示当前执行的脚本路径,%/* 表示从字符串末尾匹配 /*,保留前面部分
  • 执行 h 文件,里面基本是统一读取 husky 配置 以及 做了错误校验,然后实际执行是指向了上一级目录下的同名文件,即 .husky/pre-commit,这个就是我们要寻找的业务侧钩子脚本。
    • ${0##*/}:##/* 表示最大化匹配 */,保留后面部分
4)执行 pre-commit 脚本
  • 执行 .husky/pre-commit 文件,这个就是真正的业务侧钩子脚本,里面内容是就是跑 lint-staged。
5)执行 lint-staged 脚本
  • 运行 lint-staged 命令时,首先是要读取 lint-staged 配置,在 .lintstagedrc 文件里(部分项目可能在 package.json 里配置的),里面就是对不同类型的文件跑不同的命令
    • 在这里插入图片描述
6)执行成功 or 失败
  • 如果命令执行成功,pre-commit 钩子就顺利执行完成了,接着会往下走流程,走 commit-msg 钩子,做 提交信息的格式校验,大致流程类似。
  • 如果执行异常,钩子会中断,不会往下走,commit 失败。如异常命令有抛出信息会在命令行输出。

四、问题解决:

回到最初提到的 bigfish 项目 commit 失效问题。

1. 问题原因:

在代码提交时有warning提示,翻译下来就是 .husky 文件夹下的两个文件是不可执行的,

其实就是 .husky 里的这两个钩子文件没有被赋予可执行权限。

  • 如果这俩文件是在Windows下创建后上传的,在mac下把项目拉下来后就不可执行了。

2. 解决方式:

方式一:

  • 在项目根目录下运行命令,给钩子文件手动赋予可执行权限,
    • chmod +x .husky/commit-msg .husky/pre-commit

方式二:(推荐)

  • 升级 husky 版本到 v9,修改 package.json 里的 preare 命令为 “husky”,然后运行 npm run prepare
    • husky v9 版本更新日志里有一项变更,通过自动设置正确的文件权限,解决了 husky v8 中的这个权限问题。

3. 全局format:

解决完后,建议执行一次 npm run format 命令,即 prettier,对全局做一次代码格式化。
因为每次 commit 校验的时候项目虽然会自动执行 format,但只对修改的文件执行,建议提前对项目所有文件 format 处理下。

五、IDE自带git工具问题:

可能有些人会遇到使用 vscode 或 在线编辑器 等IDE时,自带的 git 管理工具无法 commit,执行时会立即报错。

1. 问题原因:

可能你使用了 nvm 等 node 管理工具,使用 git 工具可能会无法 commit,原因是执行 husky 命令时识别不出 node 环境,详见链接,需要补充环境配置。

2. 解决方式:

在 .husky/pre-commit 和 .husky/commit-msg 文件内容里的 npx执行命令 之前,添加环境配置代码:

待添加的环境配置代码内容:

  • 方式一:(个人搜寻并组合出来的)
if [ -s "$HOME/.nvm/nvm.sh" ]; then# First load nvm and provide access to the nvm command.export NVM_DIR="$HOME/.nvm/nvm.sh". "$(dirname $NVM_DIR)/nvm.sh"# Use the nvm ls command to detect the version being used.export NVM_DIR="$HOME/.nvm"a=$(nvm ls | grep 'node')b=${a#*(-> }v=${b%%[)| ]*}# Export the current version in your path for husky to find.export PATH="$NVM_DIR/versions/node/$v/bin:$PATH"
fi
  • 方式二:(官方文档里的,待验证)
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # 加载 nvm

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/445023.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PMP--冲刺题--解题--161-170

文章目录 4.整合管理--1.制定项目章程--当各方的认知、理解、掌握的信息不一致的时候,相对最好的方法就是共同确认项目相关文件/计划中的具体内容(是否项目真的存在这个交付物)。161、 [单选] 在一个与高级经理的项目状态会议中,项…

动态规划-路径问题——931.下降路径最小和

1.题目解析 题目来源:931.下降路径最小和——力扣 测试用例 2.算法原理 1.状态表示 我们可以开辟一个dp表,多开辟一行两列用来存储虚拟位置,dp[i][j]表示从第一行到该位置的最小路径和 2.状态转移方程 由于要找到最小路径和,并且由…

springboot将logback替换成log4j2

一 为何要替换成log4j2 1.1 log4j2的优点 log4j2使用了两种方式记录日志:AsyncAppender和AsyncLogger。 1.AsyncAppender使用队列异步记录日志,但是一旦队列已满,appender线程需要等待。2.AsyncLogger是采用Disruptor,通过环形…

Android Framework AMS(05)startActivity分析-2(ActivityThread启动到Activity拉起)

该系列文章总纲链接:专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明: 说明:本章节主要解读AMS通过startActivity启动Activity的整个流程的整个流程的第二阶段:从ActivityThread启动到Activity拉起。 第一阶段文…

【Unity精品源码】打造甜蜜的三消游戏:Candy Match 3 Kit

最近总熬夜,肝不好,大家都叫我小心肝。 📂 Unity 开发资源汇总 | 插件 | 模型 | 源码 💓 欢迎访问 Unity 打怪升级大本营 在游戏开发的世界中,三消游戏以其简单易上手、趣味性强的特点,一直深受玩家喜爱。…

【HTTPS】深入解析 https

我的主页:2的n次方_ 1. 背景介绍 在使用 http 协议的时候是不安全的,可能会出现运营商劫持等安全问题,运营商通过劫持 http 流量,篡改返回的网页内容,例如广告业务,可能会通过 Referer 字段 来统计是…

第十一章 缓存之更新/穿透/雪崩/击穿

目录 一、什么是缓存 二、缓存更新策略 2.1. 缓存主动更新策略 2.1.1. Cache Aside模式(主流)‌ 2.1.2. Read/Write Through模式‌ 2.1‌.3. Write Behind模式‌ 2.1.4. 总结 三、缓存穿透 四、缓存雪崩 五、缓存击穿 5.1. 互斥锁实现 5.1.1…

Elasticsearch学习笔记(五)Elastic stack安全配置二

一、手动配置http层SSL 通过前面的配置,我们为集群传输层手动配置了TLS,集群内部节点之间的通信使用手动配置的证书进行加密,但是集群与外部客户端的http层目前还是使用的自动配置,集群中HTTP的通信目前仍然使用自动生成的证书ht…

SQL Injection | MySQL 数据库概述

关注这个漏洞的其他相关笔记:SQL 注入漏洞 - 学习手册-CSDN博客 0x01:MySQL 数据库简介 MySQL 是一个流行的关系型数据库管理系统(RDBMS),它基于 SQL (Structured Query Language)进行操作。My…

Python库matplotlib之六

Python库matplotlib之六 动画FuncAnimation构造器成员函数应用例子 动画 Matplotlib基于其绘图功能,还提供了一个使用动画模块,生成动画的接口。动画是一系列帧,其中每个帧对应于图形上的一个图。 Matplotlib使用两个类来实现动画&#xff…

Backend - MySQL Server、HeidiSQL

目录 一、MySQL Server (一)官网下载 (二)安装与配置 二、HeidiSQL软件 (一)安装 1. 官网下载 2. 打开 3. 使用 (1)打开服务 (2)新增数据库 ​&#xff…

python networkx 计算路径A*

import matplotlib.pyplot as plt # 导入 Matplotlib 工具包 import networkx as nx # 导入 NetworkX 工具包 from typing import List# 初始化空的无向图 graph nx.Graph() # 向图中添加多条赋权边: (node1,node2,weight) graph.add_weighted_edges_from([(1, 2, 50),(1, 3…

集合框架05:List接口使用、List实现类、ArrayList使用

视频链接:13.11 ArrayList使用_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1zD4y1Q7Fw?p11&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.List接口使用代码举例 package com.yundait.Demo01;import java.util.ArrayList; import java.util.List;pu…

dowhy中反驳实验怎么做?

首先,我们打开最新的dowhy版本网站。 https://www.pywhy.org/dowhy/v0.11.1/index.html 我们主要看标题栏的User Guide和Examples就可以了,如果在User Guide 里找不到使用方法,就去Examples里找例子,里面的数据读取修改为自己的数…

Copilot Coaching新功能铸就Word更强

Copilot 的意思是副驾驶。 现在,您的副驾驶教练来了:Copilot Coaching Copilot Coaching 是 Word 中的一项新 Copilot 功能,可在您查看内容时为您提供支持,以实现语法和拼写之外的改进 - 帮助您澄清想法,并为您提供有…

前端反馈弹框组件封装

一、需求背景 需要针对某个功能进行用户调查反馈&#xff0c;设计一个弹框&#xff0c;进行后端入表记录&#xff0c;以便后期进行数据分析。 二、实现UI 三、代码留存 以vue为例 <template><div class"advice-container"><van-dialogv-model"…

【父子线程传值TransmittableThreadLocal使用踩坑-及相关知识拓展】

文章目录 一.业务背景二.TransmittableThreadLocal是什么&#xff1f;三.问题复现1.定义注解DigitalAngel2.定义切面3.TransmittableThreadLocal相关4.线程池配置信息5.Controller6.Service7.测试结果8.问题分析9 解决办法及代码改造10.最终测试&#xff1a; 四.与 ThreadLocal…

02复写零

复写零 我们先进行异地复写&#xff1a;代码如下 public class Test {public static void main(String[] args) {int []array {1,0,2,3,0,4};duplicateZeros(array);}public static void duplicateZeros(int[] arr) {int [] elemnew int[arr.length];for(int cur0,dest0;des…

QD1-P17 HTML 下拉框标签(select、option)

本节学习 HTML 常用标签&#xff1a;select和option ‍ 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p17 ‍ 知识点1&#xff1a;select标签用法 演示 ​​ HTML <select name"city"><option>北京</option><option>上海</opti…

新版Win32高级编程教程-学习笔记01:应用程序分类

互联网行业 算法研发工程师 目录 新版Win32高级编程教程-学习笔记01&#xff1a;应用程序分类 控制台程序 强烈注意 窗口程序 启动项 程序入口函数 库程序 静态库 动态库程序 几种应用程序的区别 控制台程序 本身没有窗口&#xff0c;其中的doc窗口&#xff0c;是管…