吾八哥博客

您现在的位置是:首页 > DevOps > 代码管理 > 正文

代码管理

git实现代码规范提交的拦截机制

吾八哥2020-04-18代码管理3299

背景

在代码管理的过程中,往往需要对代码提交信息进行规范管理,例如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来查看,如下图:

企业微信截图_9dc0b0cd-7b3d-40fd-8117-17354e33307a.png

这里的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软连,这样所有仓库都能共用这个钩子了。