不使用 Husky 和 Lint-staged,实现 Git 提交前自动格式化代码

大家好,我是农村程序员,独立开发者,行业观察员,VSCode 插件批发商,前端之虎陈随易。

我会在这里分享关于 独立开发编程技术思考感悟 等内容,欢迎关注。

技术群与交朋友请在个人网站 👆 联系我,如果你觉得本文有用,一键三连 (点赞评论转发),就是对我最大的支持~


在前端项目中,代码格式化是保证代码质量和团队协作的重要环节。

很多团队使用 husky + lint-staged 来实现 Git 提交前的自动格式化,但这种方案需要安装额外的依赖,增加了项目的复杂度。

本文将介绍如何直接使用 Git 原生的 Hooks 机制,不依赖任何第三方库,实现同样的功能。

为什么不用 Husky?

传统方案的问题

使用 husky + lint-staged 的典型配置:

json 复制代码
{
    "devDependencies": {
        "husky": "^9.0.0",
        "lint-staged": "^15.0.0",
        "prettier": "^3.0.0"
    },
    "scripts": {
        "prepare": "husky install"
    },
    "lint-staged": {
        "*.{js,ts,jsx,tsx}": "prettier --write"
    }
}

缺点:

  1. 需要安装多个依赖包(husky、lint-staged)
  2. 需要额外的配置文件(.husky 目录)
  3. 团队成员克隆项目后需要运行 npm install 才能启用 hooks
  4. 依赖包的版本更新可能带来兼容性问题

原生方案的优势

直接使用 Git Hooks:

  1. 零依赖 - 只需要 prettier(或其他格式化工具)
  2. 简单直接 - 一个 shell 脚本文件即可
  3. 性能更好 - 没有额外的 Node.js 进程启动开销
  4. 完全控制 - 可以自定义任何逻辑

Git Hooks 基础知识

什么是 Git Hooks?

Git Hooks 是 Git 在特定事件(如提交、推送等)发生时自动执行的脚本。这些脚本存放在项目的 .git/hooks/ 目录下。

常用的 Hooks:

  • pre-commit - 提交前执行(本文重点)
  • commit-msg - 提交信息验证
  • pre-push - 推送前执行
  • post-merge - 合并后执行

为什么 .git/hooks/ 不在版本控制中?

.git/ 目录默认不被 Git 跟踪,所以 .git/hooks/ 中的脚本无法通过 Git 共享给团队成员

这也是 husky 存在的主要原因之一 - 它通过在 package.json 中配置,让团队成员在 npm install 时自动设置 hooks。

如何分享 Git Hooks?

有几种方法:

  1. 文档说明 - 在 README 中说明如何手动复制脚本
  2. 初始化脚本 - 提供一个设置脚本,团队成员运行一次即可
  3. Git 2.9+ 的 core.hooksPath - 将 hooks 目录设置为可追踪的路径

实现方案

直接修改 .git/hooks/pre-commit

创建 pre-commit 脚本

.git/hooks/pre-commit 文件中写入以下内容:

bash 复制代码
#!/usr/bin/env sh
# Git pre-commit hook - 自动格式化暂存的文件

echo "正在检查暂存文件..."

# 获取所有暂存的文件(只包括添加和修改的文件)
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|jsx|tsx|vue|json|md|yaml|yml|css|scss|less|html)$')

if [ -z "$STAGED_FILES" ]; then
    echo "没有需要格式化的文件"
    exit 0
fi

echo "正在格式化以下文件:"
echo "$STAGED_FILES"

# 将文件列表转换为数组并逐个格式化
echo "$STAGED_FILES" | while IFS= read -r file; do
    if [ -f "$file" ]; then
        bunx prettier --write "$file"
        git add "$file"
    fi
done

echo "✓ 代码格式化完成"
exit 0

安装 Prettier

只需要一个依赖:

bash 复制代码
npm install -D prettier
# 或
bun add -d prettier

测试

创建一个格式不规范的测试文件:

javascript 复制代码
// test.js
const obj = { a: 1, b: 2, c: 3 };
const fn = (x, y) => {
    return x + y;
};
console.log(obj);

提交文件:

bash 复制代码
git add test.js
git commit -m "测试自动格式化"

Hook 会自动运行,输出类似:

csharp 复制代码
正在检查暂存文件...
正在格式化以下文件:
test.js
test.js 24ms
✓ 代码格式化完成
[main abc1234] 测试自动格式化
 1 file changed, 3 insertions(+)

查看格式化后的文件:

javascript 复制代码
// test.js - 已格式化
const obj = { a: 1, b: 2, c: 3 };
const fn = (x, y) => {
    return x + y;
};
console.log(obj);

高级用法

支持多种格式化工具

bash 复制代码
#!/usr/bin/env sh

echo "正在格式化代码..."

STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)

# JavaScript/TypeScript 文件使用 Prettier
JS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(js|ts|jsx|tsx)$')
if [ -n "$JS_FILES" ]; then
    echo "$JS_FILES" | xargs bunx prettier --write
    echo "$JS_FILES" | xargs git add
fi

# CSS/SCSS 文件使用 stylelint
CSS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(css|scss)$')
if [ -n "$CSS_FILES" ]; then
    echo "$CSS_FILES" | xargs bunx stylelint --fix
    echo "$CSS_FILES" | xargs git add
fi

# Python 文件使用 black
PY_FILES=$(echo "$STAGED_FILES" | grep -E '\.py$')
if [ -n "$PY_FILES" ]; then
    echo "$PY_FILES" | xargs black
    echo "$PY_FILES" | xargs git add
fi

echo "✓ 格式化完成"
exit 0

添加 ESLint 检查

bash 复制代码
#!/usr/bin/env sh

echo "正在检查代码..."

STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|jsx|tsx)$')

if [ -z "$STAGED_FILES" ]; then
    exit 0
fi

# 先格式化
echo "$STAGED_FILES" | xargs bunx prettier --write
echo "$STAGED_FILES" | xargs git add

# 再进行 ESLint 检查
echo "运行 ESLint..."
echo "$STAGED_FILES" | xargs bunx eslint

# 如果 ESLint 失败,阻止提交
if [ $? -ne 0 ]; then
    echo "❌ ESLint 检查失败,请修复错误后再提交"
    exit 1
fi

echo "✓ 检查通过"
exit 0

只格式化改动的部分(增量格式化)

对于大型项目,可以使用 prettier--check 选项先检查,只格式化需要修改的文件:

bash 复制代码
#!/usr/bin/env sh

STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|ts|jsx|tsx)$')

if [ -z "$STAGED_FILES" ]; then
    exit 0
fi

echo "检查文件格式..."

# 先检查哪些文件需要格式化
NEED_FORMAT=$(echo "$STAGED_FILES" | xargs bunx prettier --list-different)

if [ -n "$NEED_FORMAT" ]; then
    echo "正在格式化以下文件:"
    echo "$NEED_FORMAT"

    # 只格式化需要的文件
    echo "$NEED_FORMAT" | xargs bunx prettier --write
    echo "$NEED_FORMAT" | xargs git add

    echo "✓ 格式化完成"
else
    echo "所有文件格式正确,无需格式化"
fi

exit 0

性能对比

Husky + Lint-staged

bash 复制代码
# 启动时间
$ time git commit -m "test"
real    0m2.341s  # 包括 Node.js 启动、lint-staged 初始化等
user    0m1.234s
sys     0m0.567s

原生 Git Hooks

bash 复制代码
# 启动时间
$ time git commit -m "test"
real    0m0.482s  # 仅 shell 脚本 + prettier 执行
user    0m0.123s
sys     0m0.089s

性能提升约 4-5 倍

总结

何时使用原生 Git Hooks?

适合的场景:

  • 小型团队或个人项目
  • 追求最小依赖和简洁配置
  • 对性能有要求的项目
  • 团队成员都熟悉 Git Hooks

不适合的场景:

  • 需要复杂的 hook 管理(多个 hooks,条件执行等)
  • 团队成员对 Git Hooks 不熟悉
  • 需要跨平台的复杂逻辑

何时使用 Husky?

适合的场景:

  • 大型团队项目
  • 需要管理多个 Git Hooks
  • 团队成员水平参差不齐
  • 需要开箱即用的解决方案

最终建议

对于大多数项目,我推荐:

  1. 开发阶段 - 使用原生 Git Hooks(简单、快速)
  2. 生产项目 - 如果团队较大,可以考虑 Husky(更容易管理)
  3. 两者结合 - 保留原生 hooks 的简洁性,通过文档和脚本帮助团队成员设置

希望这篇文章能帮助你摆脱对第三方 hooks 库的依赖,用最简单的方式实现代码自动格式化!


🔥 我的 VSCode 扩展商店:

👉 点击访问

相关推荐
我是华为OD~HR~栗栗呀1 天前
华为OD-21届考研-Java面经
java·前端·c++·python·华为od·华为·面试
詩句☾⋆᭄南笙1 天前
CSS美化网页元素
前端·css·html
凤山老林1 天前
SpringBoot 启动时执行某些操作的 8 种方式
java·开发语言·spring boot·后端
范特东南西北风1 天前
roocode + vscode + api_key = free GPT-5
前端·ai编程
golang学习记1 天前
从0死磕全栈之Next.js 缓存与数据重新验证
前端
BraveAriesZyc1 天前
axios的使用
前端
没有鸡汤吃不下饭1 天前
H5移动端页面实现快递单号条形码/二维码扫描,亲测可行!!
前端·javascript·vue.js
云枫晖1 天前
JS核心知识-模块化
前端·javascript
Asort1 天前
JavaScript设计模式(十五)——解释器模式 (Interpreter)
前端·javascript·设计模式