美文网首页
从 Git Hooks 说开去

从 Git Hooks 说开去

作者: MarsLuo | 来源:发表于2021-09-28 20:05 被阅读0次

    最近我在一个咨询项目上,为了帮助客户规范代码提交信息,我们决定建议客户使用 git hooks来实现。

    为此,我们大概了解了一下 Git Hooks的相关知识。

    一、初识 Git Hooks

    Git Hooks 是什么?

    Git Hooks 是一系列脚本, Git 允许 Git 仓库在触发某些事件时,去执行这些脚本。 我们可以通过 Git Hooks 在开发生命周期的关键节点,触发自定义的操作。

    这里的脚本可以是任何正确命名的可执行脚本。由此可见,Git Hooks 的灵活性还是很强的。

    在一个 Git 仓库中,我们可以在.git/hooks中发现一系列的文件:

    applypatch-msg.sample     pre-push.sample
    commit-msg.sample         pre-rebase.sample
    fsmonitor-watchman.sample pre-receive.sample
    post-update.sample        prepare-commit-msg.sample
    pre-applypatch.sample     update.sample
    pre-commit.sample
    

    这些文件都是不同的 Git Hooks 脚本, 当然,他们现在并不会执行。

    Git 能识别的文件名是不带sample的,所以当我们把上述文件的sample后缀去掉时,这些脚本才是有效的。

    另外,因为上述文件都是可执行的脚本,所以在执行时,要注意给与其相应的权限。

    二、Git Hooks的版本化

    我们在上面看到 Git Hooks 的相关脚本存放在 .git/hooks 目录下。但该目录并不被版本化,提交到远端。

    但是对于团队来说,保证其可版本化是非常重要的功能,否则配置新脚本,或者对已有的脚本进行变化,都是一项浩大的工程。

    经过简单的调研发现,无论是Java相关的技术栈,还是JS相关的技术栈,都有比较成熟的方案。

    Java 相关的技术栈,比如 Spring 项目,Android项目等,可以使用Gradle的相关配置功能,将配置脚本纳入版本管理中,在gradle build时,再拷贝到 .git\hooks 目录中。 具体实现步骤,大家可以参见腾云的这个项目

    Js 相关的技术栈,可以直接在Npm中使用使用 husky 来完成对应的配置。他依赖Npm的安装和配置,具体的使用方式可以参见他的项目主页

    以上两种方式,都需要依靠特定的依赖管理工具才能完成。那依赖管理工具不支持,或者没有依赖管理工具,还想完成版本化管理 Git hooks, 怎么办呢?

    Git hooks 的脚本文件都存放在.git\hooks目录下,但是该目录并不能被纳入版本管理中。经过查阅 git 的文档可知, 在17年 Git 提供了一项配置: core.hooksPath,通过它,可以将指定某个目录存放 git hook 的相关脚本。同时,该目录也可以纳入版本管理。

    执行命令如下:

    git config --add core.hookspath .mygithooks

    执行该命令后,在提交时,会自动触发.mygithooks 目录下的脚本。

    三、Git Hooks 的分类

    Git Hooks 分两种,客户端钩子 、服务端钩子。 客户端钩子会被 commit,merge,rebase 等操作触发,而服务端会被push等操作触发。

    1. 客户端钩子

    客户端钩子 分为三种,提交工作流,电子邮件流,和其他。我们这里只讨论提交工作流和其他部分。

    在 Git Hooks 中,若脚本以 exit 0退出应用,则流程会继续进行。若脚本以非0值退出,则流程会中断不会继续进行。

    下图是提交工作流钩子的生命周期:

    09-20-0-0.png

    pre commit 不带任何参数,可以通过git diff 的形式获取变更的代码。一般用来检查即将提交的代码是否有效,比如是否能通过编译,是否能通过测试等。

    prepare commit msg 带三个参数, 当前提交信息的文件路径,当前的提交类型,以及提交的SHA-1校验。 一般用来做提交信息的格式化,合并,整理等。

    commit msg 带一个参数,即当前提交信息的文件路径。 一般用来检查提交信息格式等。

    post commit 不带任何参数。 一般用于提交后发送通知等。

    其他工作流包括pre-rebase, post-rewrite, post-merge, pre-push 这些在我们日常开发过程中用的比较少, 这里就不做介绍了。

    使用git commit --no-verify 可以越过和commit相关的钩子,直接提交。

    2. 服务端钩子

    服务端的钩子在持续集成中,应用是很广泛的。

    pre-receive 会处理来自客户端的推送。 常见的就是提交后触发CI,由CI返回结果来判断能否合入。

    update 也会处理来自客户端的推送,区别是可以按照分支进行处理。 如果客户端同时推送了多个分支,仅有失败的分支会被拒绝。成功的分支仍会被更新。update 带三个参数,分别是引用分支的名字,推送前的SHA-1值, 需要更新的SHA-1值。

    post-receive 在整个过程完结以后运行。 大家最熟悉的就是提交后触发测试,打包,部署等流程。

    四、 Git Hooks的使用场景

    Git Hooks 的本质是触发器,可以在 Git 的生命周期的某些阶段触发开发人员预先编写好的脚本。 所以其使用场景并不受限。

    下面仅介绍一些我们在开发过程中可能会用到的场景。

    1. 客户端钩子

      因为客户端钩子仅在本地起作用,想要做出强制性的约束,还是只能依赖服务端的流程。

      所以客户端的钩子一般多用来做提示性,或触发一些重复手动工作。

      所以我们可以在客户端钩子中检查:

      暂存区是否还有未提交的代码。

      检查或者直接格式化提交信息。

      代码是否能够编译,是否能通过lint,是否能通过单元测试,是否达到单元测试覆盖率等等指标。

      在Push 时自动升级版本。

      在将多个提交合并成一个提交时,按照格式整理提交信息等。

    2. 服务端钩子

      服务端的钩子主要的作用有两个:一个是决定是否接受当前推送(pre-receiveupdate ),另外一个是在接受推送后(post-receive ), 触发其他操作等。

      服务端的钩子的使用场景,大家就很熟悉了,通过各种自动化的方式来对代码质量进行审查,来决定代码是否能够合入云端。如果不能合入,给出相应的提示。以及合入后,触发各种各种自动化的流程进行CICD流程。

    推荐阅读:

    https://wilsonmar.github.io/git-hooks/

    https://githooks.com/

    相关文章

      网友评论

          本文标题:从 Git Hooks 说开去

          本文链接:https://www.haomeiwen.com/subject/ezvrnltx.html