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

这篇具有很好参考价值的文章主要介绍了一个 git 仓库下拥有多个项目的 git hooks 配置方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

通常情况下,一个 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.

pre-push 脚本编写

pre-commitcommit-msg 不同,在 pre-push 钩子中需要通过其他方式来拿到发生改动的文件,大家直接看代码:

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


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

# 获取远程仓库的名字和 URL
remote="$1"
url="$2"

# 定义一个空的 git 哈希值
z40=0000000000000000000000000000000000000000

# 这个循环从 stdin 读取数据,这些数据是 git 在调用 pre-push 钩子时传递的。
# 每一行数据包括 4 个字段:本地引用名,本地最新的提交哈希值,远程引用名,远程最新的提交哈希值。
while read local_ref local_sha remote_ref remote_sha
do
    # 这段代码检查是否正在删除一个引用(例如,删除一个分支)。如果是,那么本地的 sha 值将被设置为一个空哈希值。
    if [ "$local_sha" = $z40 ] 
    then
        # Handle delete
        :
    else
        # 这段代码确定要检查哪些提交。如果远程的 sha 值是一个空哈希值,那么我们正在创建一个新的引用,所以我们需要检查所有的提交。
        # 否则,我们正在更新一个已经存在的引用,所以我们只需要检查新的提交。
        if [ "$remote_sha" = $z40 ] 
        then
            # New branch, examine all commits
            range="$local_sha"
        else
            # Update to existing branch, examine new commits
            range="$remote_sha..$local_sha"
        fi

        # 这个循环对每一个包含在 range 变量中的提交执行 git rev-list 命令,这个命令会返回一系列的提交哈希值。
        # 然后,对每个提交,我们使用 git diff-tree 命令来找到在那个提交中修改的文件。这些文件的名字被存储在 files 变量中。
        for commit in $(git rev-list "$range"); do
            # 拿到所有改动的文件名
            files=$(git diff-tree --no-commit-id --name-only -r $commit)
            for file in $files
            do
                if [[ $file == frontend/* ]]
                then
                    isFrontendChanged=true
                elif [[ $file == component-attr-panel/* ]]
                then
                    isComponentAttrPanelChanged=true
                elif [[ $file == component-template/* ]]
                then
                    isComponentTemplateChanged=true
                fi
            done
        done
    fi
done

# 改动的目录需要执行校验命令
execTask() {
    echo "root $1 pre-push"
    cd $1
    npm run type-check
}

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

if $isComponentTemplateChanged
then
    execTask "component-template" &
    task2=$!
fi

if $isComponentAttrPanelChanged
then
    execTask "component-attr-panel" &
    task3=$!
fi

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

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

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

echo "All tasks finished."

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

PS:在写脚本的时候要注意各个任务是否能并发执行,比如 lint-staged 这个任务就不能并发执行,所以在编写 pre-commit 脚本执行代码校验的时候,得改为串行。文章来源地址https://www.toymoban.com/news/detail-657835.html

到了这里,关于一个 git 仓库下拥有多个项目的 git hooks 配置方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • git在一台电脑上配置不同的仓库(多个gitee仓库、或者不同的github仓库)

    在开发过程中,我们工作的时候难免会使用到两个不同的仓库,但是正常来说一电脑默认一个参考,直接会用全局命令 但是这样只能配置一个仓库了,本文介绍在一台电脑上配置多个仓库,简单易用,请欣赏! 前提:您已经掌握了git仓库命令,不需要很会,有过配置用 CA证

    2024年02月13日
    浏览(50)
  • 一文教会你 如何在Github中创建仓库?如何将多个项目放到一个仓库中管理?如何将本地项目上传到GitHub中?

    一个混迹于Github、Stack Overflow、开源中国、CSDN、博客园、稀土掘金、51CTO等 的野生程序员。 目标:分享更多的知识,充实自己,帮助他人 GitHub公共仓库:https://github.com/zhengyuzh 以github为主: 1、分享前端+后端基础知识 2、前后端框架知识+框架使用分析 3、热门前端+后端面试题

    2024年01月17日
    浏览(52)
  • 如何从一个git服务器仓库将项目迁移到另一个git服务器仓库

    最近服务器迁移涉及到代码也需要一块迁移,梳理了一些git服务迁移指令,希望大家共享😁(从服务器A迁移到服务器B) 1. 首先将服务器A上的代码进行备份 1.1 git备份指令【从A服务器(https://gitlab.xxxx.cn)上clone代码到本地】 ​​​​ git clone --bare https://gitlab.xxxx.cn/front/ifix

    2024年02月11日
    浏览(44)
  • SpringBoot项目配置多个RabbitMQ解决方案

    目前有一个Spring Boot项目,已经接入一个RabbitMQ Broker,由于业务扩展,需要新增一个RabbitMQ Broker进行消费,由于单个Broker时通过Spring默认配置进行使用,因此需要做出修改 pom 增加properties配置 增加配置类 增加properties配置 修改配置类

    2024年02月11日
    浏览(32)
  • git 将本地已有的一个项目上传到新建的git仓库的方法

    将本地已有的一个非git项目上传到新建的git仓库的方法一共有两种 第一种方法比较简单,直接用把远程仓库拉到本地,然后再把自己本地的项目拷贝到仓库中去。然后push到远程仓库上去即可。 此方法适用于本地项目不是一个git仓库的情况。 具体步骤如下: 1、首先克隆 1

    2024年02月04日
    浏览(47)
  • 手把手教你如何拥有自己的git仓库(国内版码云)

    码云(Gitee)简介:   码云(Gitee)是 开源中国社区推出的代码托管协作开发平台,支持Git,提供免费的私有仓库托管 。Gitee目前已经成为国内最大的代码托管平台。帮助开发者存储和管理其项目源代码,且能够追踪、记录并控制用户对其代码的修改,提供稳定、高效、安

    2024年02月15日
    浏览(69)
  • Git 如何将一个项目的代码放到一个新的仓库中,但不在新的仓库中显示旧的提交记录

    场景:我想把RuoYi的代码放到一个新的仓库里,放进去之后,这个仓库会显示RuoYi之前的所有提交,如何不显示这些旧的提交? 有时候,我们可能需要将一个项目的代码放到一个新的仓库中,但是我们又不想在新的仓库中显示旧的提交记录。这可能是因为旧的提交记录包含一

    2024年02月07日
    浏览(46)
  • 【Git】第一次将本地项目仓库推代码到空的远程仓库方法以及报错的解决方案

    完成上述三步之后,在弹出来的对话框中选择自己的项目目录, 点确定,就可以在文件管理器中看到目录下生成了一个隐藏目录 “ .git ” 右键项目目录,找到Git,根据图示找到remote 在弹出来的对话框中,输入自己远程仓库的地址 点击ok,输入验证信息,连接完毕。 点击p

    2024年02月15日
    浏览(45)
  • IntelliJ IDEA - 一篇解决如何多模块项目提交到同一个 Git 仓库

    事情是这样的,最近新建了一个项目(多模块),这个不必多说大家就知道长什么样子(文件结构),问题是在我写完后想提交项目到 Git 仓库时,发现每个模块都要设置 Remote Git 地址,那么相当于是把每一个模块独立一个 Git 仓库地址,这个是我这个项目中不希望出现的(当

    2024年02月15日
    浏览(55)
  • 服务器上一个域名对应多个前端项目的nginx转发配置

    场景: 当有两个前端项目A,B的时候,项目A(对应端口8000)和项目B(对应端口8001)分别部署在服务器的不同位置,通过服务器ip+端口都能正常访问单独的项目A和项目B;现在要求两个项目共用一个域名~~也就是说访问http://10.111.182.xxx:8000的时候默认访问项目A的资源,访问htt

    2024年02月05日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包