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