git代码提交 设置日志模板 对用户提交日志注释进行校验

发布时间 2023-07-04 11:01:27作者: cosmocosmo

背景:

由于公司项目管理需要,对开发人员的提交日志进行规范性约束。作为兼职的devops工程师,责无旁贷的去吭哧吭哧的研究了。公司主要使用git管理代码,gogs托管。作为领导眼中分分钟解决的问题,在真实上手研究还是需要一些时间成本的(鄙人主职还是研发)。

思路:

1、利用度娘和biying搜索了大量解决方案,发现都是指向git hook这个钩子来实现具体的业务场景。

比如 [1] 通过修改客户端的prepare-commit-msg.sample和commit-msg.sample,实现客户端的commit校验,但必须开发人员自己在库中的git/hook目录下修改相应文件,很难控制约束不太自觉的人员;又如 [2] 以Android项目为例子,使用Gradle脚本,当用户执行构建操作的时候,我们执行配置提交模板的脚本,通过脚本将配置的模板拷贝到用户的".git/hooks"目录下。再如 [3] 提出了一种解决.git文件夹不会被git跟踪,所以.git/hooks目录下的hooks钩子无法提交,就不能和他人共享钩子脚本。通过第三方的插件如:husky和yorkie解决上述问题。但上述三种方案都是在客户端侧对git提交的注释进行约束,不太能满足我们的诉求。

2、[3] 和 [4] 中还描述了hook是分客户端hook和服务器hook的,pre-receive、update和post-receive是服务器hook,只需要修改对应代码库的服务器hook文件,就可以对所有开发人员的push 提交注释进行校验。于是思考服务器hook也许可以解决我们的问题。

3、思考如何在执行pre-receive时获取注销,并对注释格式进行校验。[5] 给了我启发。

解决方案

1、修改代码库中git/hook目录下的pre-receive

regex="^修改类型:(新功能|缺陷) TB编号\+主题:.{1,100} 是否自测:(是|否)"
echo "regex: "$regex

## 定义注释出错提示信息
tips_msg="修改类型:新功能/缺陷 TB编号+主题: 是否自测:是/否"

validate_commit_message()
{
   oldrev=$(git rev-parse $1)
   newrev=$(git rev-parse $2)
   refname="$3"
   #echo 'Old version: '$oldrev
   #echo 'New version: '$newrev
   #echo 'Branch: '$refname

   ## git 命令
   #GITCMD="git"
   ## 按时间倒序列出 commit  找出两个版本之间差异的版本号集合  oldrev~newrev
   commitList=`git rev-list $oldrev..$newrev`
   #echo 'commitList: '$commitList

   split=($commitList)
   #echo 'split: '$split

   # 遍历数组
   for s in ${split[@]}
   do
      #echo “$s”
      #通过版本号获取仓库中对象实体的类型、大小和内容的信息
      #比如提交人、作者、邮件、提交时间、提交内容等
      currentContent=`git cat-file commit $s`
      #echo 'Commit obj: '$currentContent
      #获取提交内容
      msg=`git cat-file commit $s | sed '1,/^$/d'`
      #echo 'msg: '$msg

        ## merge合并分之直接放行
        if [[ $msg == *"Merge branch"* ]]; then
        echo "Merge branch...skip the checking"
        else
            ## 做内容校验
            match=`echo $msg | grep -nE "(${regex})"`
            echo 'Match result: '$match

            ## 找到匹配说明是符合规范的
            if [ "${match}" != "" ]; then
          ## 校验注释长度
          msg_length=${#msg}
          #echo "Msg length: ${msg_length}"
          if [[ ${msg_length} -lt ${COMMIT_MESSAGE_MIN_LENGTH} ]]; then
            echo -e "Error: Commit message should be bigger than ${COMMIT_MESSAGE_MIN_LENGTH} and current commit message length: ${msg_length}"
            exit 1
          fi

          ### 找到匹配内容做相应处理,如fix ,校验pom文件等
          #if [[ "${match}" =~ "fix:" ]]; then
            ## 如果是修补bug,规范有点获取到fix中的ID,然后调用禅道对外的API关闭,其他场景类似
          #fi

          # 是否开启校验和master分之
          isMaster=$(echo $refname | grep "master$")
          if [ -n "$isMaster" ]; then
            # 如果是master分之,并且pom文件发生了变更,判断pom文件是否含有sonapshot的引用
            pomfile=`git diff --name-only ${oldrev} ${newrev} | grep -e "pom\.xml"`
            if [[ "${pomfile}" != "" ]]; then
              #echo $pomfile
              ## 获取pom文件更新的内容
              pomcontent=`git show $newrev:$pomfile`
              #echo $pomcontent
              ## 校验pom文件是否包含snapshot版本
              if [[ $pomcontent =~ 'SNAPSHOT' ]]; then
                echo -e "Error: Snapshot version cannot exist in master branch!"
                exit 1
              fi
            fi
          fi

          ## 其他操作
          echo "Commit Success!"
        else
          echo -e "Error: Commit comments message should be started with [${tips_msg}]..."
          exit 1
        fi
          fi
   done
}

####### 执行入口###########
pre_receive()
{
validate_commit_message $1 $2 $3
}

if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
    # Output to the terminal in command line mode - if someone wanted to
    # resend an email; they could redirect the output to sendmail
    # themselves
    #pre_receive $2 $3 $1
    echo $1'+'$2'+'$3
else
    while read oldrev newrev refname
    do
       #pre_receive $oldrev $newrev $refname
       echo "1"
       echo $oldrev' '$newrev' '$refname
       echo "2"
       pre_receive $oldrev $newrev $refname
    done
fi
"/home/git/gogs/gogs" hook --config='/home/git/gogs/custom/conf/app.ini' pre-receive

2、commit后 push到远端服务器 若注释不符合规范

 3、git commit --amend 修改注释 [6]

 4、修改注释成满足要求格式后push成功

 

 

 

 

 

 

 

参考:

[1] https://zhuanlan.zhihu.com/p/456519458

[2] https://juejin.cn/post/7208111879151009848

[3] https://juejin.cn/post/6974301879731748900

[4] https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

[5] https://blog.csdn.net/xiaoll880214/article/details/105916898

[6] https://blog.csdn.net/c46550/article/details/116574128