git实现代码规范提交的拦截机制
背景
在代码管理的过程中,往往需要对代码提交信息进行规范管理,例如email要为公司邮箱,名字要为真实姓名,commit message要符合规范,这样方便后期代码统计,代码追溯源头。这里以拦截提交人邮箱和message为例,邮箱必须为公司邮箱,message必须是feat、bugfix、hotfix三种中的一种,例如:"feat:xxx"
实现方法
git提供了服务端钩子的机制,可以通过服务端钩子来实现提交拦截,那么如何拦截呢?拦截什么信息?下面进一步分析:
commit信息
在git里每个commit的信息包含如下内容:
- committer_name 提交人名字
- committer_email 提交人邮箱
- committed_date 提交时间
- created_at 提交时间
- message 提交描述信息
- ...
本地可以通过git log来查看,如下图:

这里的Author和message都是在本地可以任意写,提交到服务器里后存储的也是本地写的这个信息,如果不进行规范管理,这个信息就非常混乱了。
服务端钩子
相关的文档可以参考:
https://git-scm.com/book/zh/v2/%E8%87%AA%E5%AE%9A%E4%B9%89-Git-Git-%E9%92%A9%E5%AD%90
https://git-scm.com/docs/githooks#pre-receive
pre-receive钩子来实现我们要的功能,脚本代码如下:
#!/bin/bash
# pre-receive hook for Commit Check
ZERO_COMMIT="0000000000000000000000000000000000000000"
while read OLD_REVISION NEW_REVISION REFNAME ; do
    if [ "$NEW_REVISION" == "$ZERO_COMMIT" ]; then
    	exit 0
    fi
   if [ "$OLD_REVISION" != "$ZERO_COMMIT" ]; then
        REVISIONS=$(git rev-list $OLD_REVISION..$NEW_REVISION --not --all)
    else
        REVISIONS=$(git rev-list $NEW_REVISION --not --all)
    fi
    for REVISION in $REVISIONS; do
    	# 提交人邮箱必须符合规范
        REGEX_AUTHOR="^author (.*) <(.*@5bug.wang)>"
        COMMIT_INFO=`git cat-file commit $REVISION`
        COMMIT_AUTHOR=`echo -E "$COMMIT_INFO" | grep author`
        if [[  "$COMMIT_AUTHOR" =~ $REGEX_AUTHOR ]]; then
            # ...
        fi
        # 提交信息必须符合规范
        REGEX_MESSAGE='^(feat|bugfix|hotfix)(\(.+\))?:.{1,50}'
        COMMIT_INFO=`git cat-file commit $REVISION`
        COMMIT_MESSAGE=$(git cat-file commit $REVISION | sed '1,/^$/d')
        if [[ "$COMMIT_MESSAGE" =~ $REGEX_MESSAGE ]]; then
            # ...
        fi     
    done    
done我们的代码管理系统是gitlab,所以pre-receive钩子文件需要放在gitlab服务器的代码文件存放目录下,每个仓库都有一个存储目录,需要把pre-receive文件放在服务器的相应的仓库的customhook目录下,我一般是通过软连来实现的,同时利用gitlab的webhook钩子里的仓库变化通知来实现新仓库的自动加customhook软连,这样所有仓库都能共用这个钩子了。
 
             
                     
                                