Git Hook客户端实践

前言

Git 为我们提供了 hook 功能,具体可以参考官网:https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

本文仅介绍 commit-msg 内容

见名知义,hook msg 提交操作,对提交的内容进行处理,比如我们常使用的 gerrit 就是在这一步中为我们增加了随机的 changeId 内容。

初识

对于一个执行 git init 的 Git 项目,会自动生成 Git 所需文件,处于 .git 文件夹中。

mi@mi-OptiPlex-7050:~/work/TestGit$ tree -a
.
└── .git
    ├── branches
    ├── config
    ├── description
    ├── HEAD
    ├── hooks
   ├── applypatch-msg.sample
   ├── commit-msg.sample
   ├── fsmonitor-watchman.sample
   ├── post-update.sample
   ├── pre-applypatch.sample
   ├── pre-commit.sample
   ├── prepare-commit-msg.sample
   ├── pre-push.sample
   ├── pre-rebase.sample
   ├── pre-receive.sample
   └── update.sample
    ├── info
   └── exclude
    ├── objects
   ├── info
   └── pack
    └── refs
        ├── heads
        └── tags

其中 hooks 目录就是我们需要关注的,Git 贴心的为我们生成了一些 smaple 文件,算是教程吧。

接下来我们创建文件 commit-msg 来实现我们控制提交格式的简单需求:提交内容必须以 TYPE 开头,包含[BugFix] 、[Feature] 、[Stability] 、[Performance] 、[Improvement] 、[CTS] 、[Test]。

实现

其实通过 sample 我们可以看到,整个内容就是一个脚本,我们只要通过脚本完成我们的需求就可以了。比如修改 msg 内容(修改文件)、阻止提交(exit 1)

开始动手之前,我们需要知道如何获取到已经提交的文本,才能进行处理,方法有很多,比如 gerrit 的方式,以文件的形式进行获取,然后通过 awk 对文件进行处理。

MSG="$1"

当然,使用 cat 命令读取文件就拿到了字符串

msg=`cat $1`

接下来,根据正则进行判断,是否满足要求,如果不满足要求,提示错误信息,并通过 exit 1 进行结束

#!/bin/sh
msg =`cat $1`
SUCCESS=1
FAILED=0
 
verify_type(){
    type_flag=`echo $1 |egrep '^\[BugFix\]|^\[Feature\]|^\[Stability\]|^\[Performance\]|^\[Improvement\]|^\[CTS\]|^\[Test\]'`
    if [ "$type_flag" = "" ];then
        return $FAILED
    else
        return $SUCCESS
    fi
}
 
verify_type "$msg"
verify_type_result=$?
 
if [ "$FAILED" -eq "$verify_type_result" ];then
    echo "commit 失败!提交类型必须是[BugFix]、[Feature]、[Stability]、[Performance]、[Improvement]、[CTS]、[Test]!  具体格式参考:https://wiki.n.miui.com/pages/viewpage.action?pageId=129267247"
    exit 1
fi

这样就完成了我们的需求。

但是我们不按照规则执行,仍然会提交成功

mi@mi-OptiPlex-7050:~/work/TestGit$ git commit -m "第一次提交"
提示:因为没有将钩子 '.git/hooks/commit-msg' 设置为可执行,钩子被忽略。您可以通过
提示:配置 `git config advice.ignoredHook false` 来关闭这条警告。
[master (根提交) e112664] 第一次提交
 1 file changed, 2 insertions(+)
 create mode 100644 fist-commit

Git 也给了我们提示,没有将 .git/hooks/commit-msg 文件赋予可执行权限,我们与已授权:

mi@mi-OptiPlex-7050:~/work/TestGit$ chmod +x .git/hooks/commit-msg
mi@mi-OptiPlex-7050:~/work/TestGit$ git add .
mi@mi-OptiPlex-7050:~/work/TestGit$ git commit -m "第二次提交"
.git/hooks/commit-msg: 2: .git/hooks/commit-msg: msg: not found
commit 失败!提交类型必须是[BugFix]、[Feature]、[Stability]、[Performance]、[Improvement]、[CTS]、[Test]!  具体格式参考:https://wiki.n.miui.com/pages/viewpage.action?pageId=129267247

就已经完成了需要的功能。

总结

Git Hook 中的 commit-msg,实现很容易,但是有以下几点需要注意:

1、配置无法下发到客户端。.git 目录下文件不参与 git 工程管理部分,gerrit 也是通过 scp 将文件拷贝到对应的目录下,如下:

git clone "ssh://sunhao8@git.mioffice.cn:29418/platform/packages/apps/MiuiHome" && scp -p -P 29418 sunhao8@git.mioffice.cn:hooks/commit-msg "MiuiHome/.git/hooks/"

2、需要对 commit-msg 增加执行权限

具体可以参考:http://gerrit.pt.mioffice.cn/c/platform/packages/apps/MiuiSystemUI/+/1395805