• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

git 仓库下拥有多个项目的 git hooks 配置方案

武飞扬头像
谭光志
帮助1

前言

通常情况下,一个 git 仓库就是一个项目,只需要配置一套 git hooks 脚本就可以执行各种校验任务。对于 monorepo 项目也是如此,monorepo 项目下的多个 packages 之间,它们是有关联的,可以互相引用,所以当成一个项目也没问题。

但是也有一种情况,一个 git 仓库下的多个项目之间是彼此独立的,比如 git 仓库下存在前端项目、后端项目、文档项目等等。这时候就需要为每个项目配置不同的 git hooks 脚本了,因为不同的项目有可能校验规则不一样。

本文主要探讨一下如何为不同的项目配置 git hooks 脚本。

PS:配置 git hooks 脚本使用 huksy

方案一:每个项目下都配置一套 git hooks 脚本

假设仓库拥前后端两个项目:

frontend
backend

那么我们需要在每个项目下安装 husky,同时要在 package.json 中配置一下 prepare 脚本(这里以前端项目为示例):

# package.json
{
	"scripts" {
		"prepare": "cd .. && husky install frontend/.husky"
	}
}

然后按照 husky 文档创建 pre-commitcommit-msg 钩子文件:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# pre-commit
cd frontend
npx lint-staged
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# commit-msg
cd frontend
FORCE_COLOR=1 node scripts/verifyCommitMsg.mjs $1

上面展示的是前端项目的 git hooks 创建过程,后端项目按照同样的过程创建即可。目前仓库的目录结构如下:

frontend
	.husky
		- pre-commit
		- commit-msg
backend
	.husky
		- pre-commit
		- commit-msg

运行一段时间后,发现这个方案有问题,那就是每次触发的 git hooks 脚本都是前端项目的,后端项目提交代码根本不触发 git hooks。排查问题后发现是 git 仓库的配置引起的,打开 .git/config 文件:

[core]
	hooksPath = frontend/.husky

上面 hooksPath 路径对应的就是 git hooks 的目录位置,目前 git 只支持指定一个目录作为 git hooks 的位置。所以第一个方案不靠谱,达不到我们想要的效果。

方案二:只在根目录下配置一套 git hooks 脚本

第二个方案是将 git hooks 放在项目根目录下,统一在根目录里执行各个子项目的校验脚本。这个方案有以下几个步骤:

修改 husky 安装位置

在每个项目下安装 husky 时,要把 git hooks 钩子目录设置在根目录:

# package.json
{
	"scripts" {
		"prepare": "cd .. && husky install .husky" # 放到根目录
	}
}

同时 .git/config 文件也要修改一下:

[core]
	hooksPath = .husky # 改为根目录

在 git hooks 中进行各个子项目的校验操作

这里以 commit-msg 作为示例编写一个脚本:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# 拿到所有改动的文件名
changedFiles=$(git diff --cached --name-only --diff-filter=ACM)

# 判断目录是否改动
isBackendChanged=false
isFrontendChanged=false

for file in $changedFiles
do
    if [[ $file == frontend/* ]]
    then
        isFrontendChanged=true
    elif [[ $file == backend/* ]]
    then
        isBackendChanged=true
    fi
done

# 改动的目录需要执行校验命令
# $1 $2 代表传给函数的第一个、第二个参数
execTask() {
    echo "root $1 commit-msg"
    cd $1
    FORCE_COLOR=1 node scripts/verifyCommitMsg.mjs $2
}

if $isFrontendChanged
then
    execTask "frontend" $1 & # 使用 & 让任务在后台执行
    task1=$! # 保存任务 id
fi

if $isBackendChanged
then
    execTask "backend" $1 &
    task2=$!
fi

if [[ -n $task1 ]]; then
    wait $task1
fi

if [[ -n $task2 ]]; then
    wait $task2
fi

echo "All tasks finished."

上面脚本的逻辑是这样的:

  1. 每次 git 提交代码时,判断一下当前所有改动的文件是属于哪个项目
  2. 文件发生改动的项目需要执行校验任务
  3. 每个校验任务都使用子进程去执行
  4. 等待所有校验任务执行结束后,输出 All tasks finished.

测试一段时间后,发现第二个方案没发生什么问题,完全满足需求。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfjjgkk
系列文章
更多 icon
同类精品
更多 icon
继续加载