自定义 Git Hook

这篇具有很好参考价值的文章主要介绍了自定义 Git Hook。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

前端同学大概都熟悉 husky 这个工具,他可以直接在项目中添加 git hooks,主要解决了 git hooks 不会同步到 git 仓库的问题,保证了每个开发人员的本地仓库都能执行相同的 git hooks。

但是 husky 毕竟是一个 JS 生态的工具,依赖于 npm 安装和 npm 的 script hook 才能达到最佳效果,放到后端项目中,初始化一堆 npm 配置文件,还需要开发人员手动安装,多多少少会显得不太合适。

恰巧我们项目一直被一个提交问题所困扰,所以我前段时间给项目写过一个命令行工具,用于初始化 git hook, 将编写 Git Hook 这个过程整理一下。

Git Hook

本文不对 git hook 类型做过多介绍,主要是针对编写 commit-msg hook 作为演示展开,commit-msg 接收一个存有当前提交信息的临时文件的路径的参数,我们可以读取这个文件获取用户提交信息, 如果该 hook 脚本以非零值退出时 Git 将放弃提交,因此,我们可以用来在提交通过前验证项目状态和提交信息。

Git Hook 示例

通常情况下,在当前项目的 <project root>/.git 目录下会有一个 hooks 目录,里面会有官方提供的各个 hook 的示例,如果没有的话也不用担心,新建一个 hooks 目录即可。

自定义 Git Hook,git,运维,前端

示例代码会有一个 .sample 后缀,去掉后缀后,hook 文件就生效了,提供的示例大部分都是 shell 编写的,我们在这里看一下示例中的 commit-msg

自定义 Git Hook,git,运维,前端

这个示例脚本的功能是检查文件中是否存在重复的 Signed-off-by 行,下面对出现的命令做逐一解释:

  1. grep '^Signed-off-by: ' "$1": 使用 grep 命令在文件中查找以Signed-off-by: 开头的行。
  2. sort: 使用 sort 命令对查找结果进行排序。
  3. uniq -c: 使用 uniq 命令计算排序后的行的数量,并将结果按数量进行排序。
  4. sed -e '/^[ ]*1[ ]/d': 使用 sed 命令删除数量为 1 的行,即只保留数量大于 1 的行。
  5. "$(...)": 将命令的执行结果赋值给变量 test。
  6. || { echo >&2Duplicate Signed-off-by lines.; exit 1; }: 如果 test 变量为空(表示没有重复的 Signed-off-by 行),则执行后面的代码块;否则,输出错误信息并退出脚本。

编写 Git Hook

提供的示例脚本比较复杂,理解起来多少有些困难,我们先使用 shell 脚本编写一个简单的示例。
这个脚本的功能是检查 commit-msg 中是否在开头添加 issue id。

#!/usr/bin/env sh

issueId=$(cat $1 | sed -n 's/^\(#[0-9]*\) .*/\1/p')

if [ ! $issueId ]
then
    echo "commit msg 必须开头添加 issue id"
    exit 1
fi

在上面这块代码中,参数 $1 是存有当前提交信息的临时文件的路径,我们通过 cat $1 读取到文件中的提交信息,然后通过 sed 去正则匹配信息中是否存在 issue id, 当没有 issueId 时,通过 exit 1 退出脚本。

  • 下图是一个校验未通过的拦截示例
    自定义 Git Hook,git,运维,前端

  • 下图是一个成功提交的示例。
    自定义 Git Hook,git,运维,前端

我们用了几行代码就实现了一个小功能,所以说编写 git hook 并不是一件复杂的事,但是对于大多数开发者而言,对于 shell 可能仅仅停留在了编写简单命令的阶段,开发起来肯定不如自己擅长的语言随心所欲,再加上一些命令可能还受限于宿主机的环境问题等等,所以我们接下来直接使用自己擅长的语言编写 git hook。

使用 NodeJS 编写 GitHook

git hook 允许你使用任何你熟悉的脚本语言,比如 perl、python、node 等等, 我们只需要在文件头部加入声明即可。

#!/usr/bin/env node

如上所示,这是一个 node 脚本的文件头,我们现在重新将使用 shell 编写的 检查 commit-msg 中是否在开头添加 issue id 的功能,使用 node 脚本实现一遍。

#! /usr/bin/env node
const fs = require('fs')

const [_, __, msgFilePath] = process.argv
const msg = fs.readFileSync(msgFilePath, { encoding: 'utf8' })
const checkIssueId = /^#\d+\s+.*/.test(msg)

if(!checkIssueId) {
    console.log("commit msg 必须在开头添加 issue id")
    process.exit(1)
}

我们通过 process.argv 获取到调用脚本时传入的参数,在通过 nodeJS 的 fs.readFileSync 方法读取到文件中的提交信息,这时就可以按照自己的需求去完善功能了,当不符合规则时,我们通过调用 process.exit(1) 结束调用进程,注意参数 1 可以是除 0 以外的任何数值,因为 git 会判断是否以非零值结束。

还能做些什么?

文中提供的示例仅仅是简单校验了一下提交信息,但实际上还可以做更多的事情,比如说直接在脚本中调用 github、gitee、gitlab…平台的 API 获取项目的 issue ID 列表,从而达到校验 issue id 是否存在的问题,再或者我们可以在 hook 中统一在提交信息尾部添加 某些信息(用户、提交文件数) 等等。

编译型语言示例

脚本语言可以直接在文件头声明即可,编译型语言是没办法这么做的,这里提供一个通用的处理方法,适用于任何语言。

基本所有语言都是支持命令调用的,比如 node xxx.js, python xxx.py, java xxxxx.class, 既然这样,我们可以直接在 shell 中调用相应的命令即可。

shell

下面以调用 java 作为示例, 我们先调用 javac 将源代码编译为 class 文件,在通过 $() 获取 java 调用的结果,因为通过 shell 获取文件内容更方便,所以我们可以直接在 shell 中调用 cat 命令获取提交信息,最终,我们只要根据调用的代码有没有返回异常信息作为判断依据即可。

#! /usr/bin/env sh

msg="$(cat $1)"

cd $(pwd)/.git/hooks
javac HookExample.java
checkMsg="$(java HookExample "$msg")"
err="$(echo $checkMsg | grep "fail: ")"

if [ "$err" != "" ]
then
	echo $err
	exit 1
fi

这里为了简单,我直接在脚本中临时编译 java 文件为 .class 文件,再调用 .class,这样其实很不合适,实际运用时,我们可以直接调用打包后的 jar 包,可以免去很多麻烦。

java

下面这段代码,我们写了一个 main 方法,直接拿到了提交信息进行检测,当不符合标准时控制台输出错误信息,我们可以统一一个错误信息的标识开头,比如当前示例的 fail: ,这样我们在 shell 中检查日志输出时可以过滤掉非异常的输出。

import java.util.regex.Pattern;  
  
class HookExample {  
    public static void main(String[] args) {  
        String commitMsg = args[0];  
        boolean checkIssueId = Pattern.matches("^#\\d+\\s+.*", commitMsg);  
        if(!checkIssueId) {  
            System.out.println("fail: commit msg 必须在开头添加 issue id");  
        }  
    }  
}

结语

虽然这是一篇编写自定义 Git Hook 的教程,但实际讲的仍然是编写脚本的问题,除了用于编写 git hook, 我们平日里还可以通过编写脚本的方式来代替无意义、重复的工作,例如创建模板代码、数据处理、文件管理、生成 mock 数据、定时执行任务等等,再或者我们可以在脚本中发起请求,直接通过命令方式获取某些数据进一步处理等等。

通过编写脚本解决日常重复性工作可以提高效率和减少人为错误,当遇到一些重复性高、繁琐的工作任务时,编写脚本来处理这些任务可以节省时间和精力。

此外,脚本还可以提高工作的准确性和一致性,由于脚本是按照预先定义的规则和流程执行的,因此可以避免人为操作带来的错误和不一致性。这对于需要高度精确和一致性的工作任务尤为重要。

当然了,通过编写脚本实现工具代替某些工作有时也会适得其反,比如某些工作明明人工操作可能仅需要一两个小时,但编写脚本可能要花半天时间,再加上可能存在bug, 这时工具的作用未必理想,所以谨记编写脚本的目的是为了提高效率而不是为了制造麻烦。文章来源地址https://www.toymoban.com/news/detail-843024.html

到了这里,关于自定义 Git Hook的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • git 提交代码 出现的错误 pre-receive hook declined

    错误提示: 问题定位: 原因是由于没有提交到master 的权限,既然定位到问题了,那么就好办,权限不足就配置权限得了呗。 解决方案: 打开网页版本,进入项目,点击 SettingsMembers,进行人员权限配置 权限配置后再次push就成功了

    2024年02月11日
    浏览(71)
  • 【Git】Git commit至Gitee报错‘remote: error: hook declined to update refs/heads/master‘的解决方法

    Git commit至Gitee报错‘remote: error: hook declined to update refs/heads/master‘的解决方法 进入到Gitee的 邮箱管理 中,取消勾选 禁止命令行推送暴露个人邮箱

    2024年02月04日
    浏览(53)
  • 【问题记录】git报错:[remote rejected] (pre-receive hook declined)

    经过排查,不是因为权限不足,是由于commit提交不规范引起的提交失败,报错如下 修改commit信息,用下面这行命令就行 然后重新push,就成功了

    2024年02月12日
    浏览(60)
  • git commit报错:running pre-commit hook: lint-staged

    running pre-commit hook: lint-staged 在项目(vue)的package.json文件中,查找 “husky” 部分,并确认其下的 “pre-commit” 钩子是否正确地引用了 lint-staged。 其中配置示例如下 (供参考,不会配的话粘过去就能用): 希望记录的问题,能够帮助到你!

    2024年02月05日
    浏览(47)
  • git提交失败之running pre-commit hook: lint-staged

    在项目中提交代码时遇到了git报错,但是很疑惑不知道为什么报错。上网差了查才发现是项目中有语法校验,在提交中git默认不允许存在很多语法错误的文件提交。 错误提示: git:running pre-commit hook:lint-staged 错误分析: 错误的意思是大概是有一个钩子,提交前检查项目代码的

    2024年02月13日
    浏览(46)
  • git push解决办法: ! [remote rejected] master -> master (pre-receive hook declined)

    项目经理远程创建了一个 空项目 ,无任何内容,给我赋予的 developer 账号权限,本地改为后提交代码试了很多次都上传不上去,报错如下: 先说结果: git push 不上去的原因在于所push的 分支权限 为 protected, 只有项目的 管理员 或具有相应权限的人才能进行 push ,要进行项目的

    2023年04月25日
    浏览(46)
  • git提交报错:husky - pre-commit hook exited with code 1 (error)

    提交代码的时候,提交错误了… 无论是使用 idea 自带的工具还是直接使用命令行都会报错 很明显报错信息: husky - pre-commit hook exited with code 1 (error) 部分人可以成功(我就不行…) 由于项目使用了husky,在提交前对代码规范进行了校验,导致报错

    2024年02月11日
    浏览(81)
  • git提交终端报husky - pre-commit hook exited with code 1 (error)

    今天像往常一样正常提交代码不知道哪里出了问题 终端“抽风”了 我没提交成功 报错如下 然后就开始找解决方法 看到最多的是commit时加上提交信息 :\\\"fix:xxxx\\\" 然后我就试了一下 发现并没有用 欸 咋整捏 (ps: 这个方法我用了之后没用 不代表他就是错的呀 可能是错误不太一样

    2024年02月11日
    浏览(65)
  • git提交时报错:husky-commit-msg hook exited with code 1 (error)

    ​问题描述: git commit 时控制台报错: 由于项目使用了husky,在提交前对代码规范进行了校验,导致报错 这种情况下无法直接push o(╥﹏╥)o ​ 解决方案: commit 时加上提交信息:“fix: xxxxx”,比如: 提交后就可以顺利push了 O(∩_∩)O ​

    2024年02月11日
    浏览(56)
  • 【已解决】git push 报错: ! [remote rejected] main -> main (pre-receive hook declined)

    git push时报如下错误: 找了好久,发现网上主要有两种解决办法: 没有权限 ,将所要push的内容所在的分支的protected权限关闭 新建其它分支 ,将项目push到新建的分支上,后期再进行merge 这两种方法都尝试了,均为解决!!!找到了一个新的解决办法,成功地解决了这个问题

    2024年02月12日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包