tags:: #commit-msg #git #commit
Git每次提交代码都需要写commit message,一般来说,commit message应该清晰明了,说明本次提交的目的,具体做了什么操作等。但是在日常开发中,开发者提交的的commit message千奇百怪,中英文混合使用,这就导致后续代码维护成本特别大,有时自己都不知道自己的fix bug修改的是什么问题。基于以上这些问题,我们希望通过某种方式来监控用户的git commit message,让规范更好的服务于质量,提高大家的研发效率。
所有项目的Commit Log的格式精确控制,增加可读性,便于查看变更历史,形成良好的git使用习惯。规范作为git hook的commit-msg和pre-receive执行,不合法无法提交。全面执行后可自动化执行以下操作:
Commit Log包含三部分header、body、footer,其中header是必须的,格式固定,body在变更有必要详细解释时使用。
commit log 格式:
xxxxxxxxxx<types>(<scopes>): <subject><空行><body><空行><footer>
注意:冒号后面必须有一个小写空格,types和scopes可为多个,中间用逗号分隔。
举例:
xxxxxxxxxxfix(service,dao): 修改产品类型时不过滤产品Type
xxxxxxxxxxrefactor(*): 修改DTO模型前缀
xxxxxxxxxxfix(language-service): Improve signature selection for pipes with argsPipes with arguments like `slice:0` or `slice:0:1` should not producediagnostic errors.
xxxxxxxxxxfunc(core,logic): 添加礼包审核添加商品编辑审核状态和回调,blablablablaPRD:https://km.sankuai.com/page/194127085
英文,小写。必须为下列中一个或多个:
英文,小写。表示变更的包或模块范围,可多个组合,若涉及范围较大,可用 * 代替。各服务可以自行定义,组内同学可轻易理解。通用scope列表如下:
dto: dto结构变化
core: core包
service: service层代码
dao: dao层代码
sql: sql代码变更
除上述通用字段外,Scope中各方向==可自行定义关键字==。例如以下为商品平台中所定义字段:
活动: 活动信息相关
stock: 库存相关
product: 商品相关
idl: IDL文件变化
中文。标题简述修改,结尾不要有句号。
中文。修改的背景(为什么做这次修改),说明修改逻辑。
中文。可以放置需求wiki或task链接,对以后其他同学blame很有用。
Java代码块
xxxxxxxxxx(^(\w+)\(([\w+,.\-_*]+?)\): .+(.|\n)*)|(^Automatic merge(.|\n)*)|(^Merge (.|\n)*)
本地hook:可自行加一个git hook,文件名:commit-msg,放到.git/hooks/ 下,确保不合法commit log格式无法提交,在自己的工程里执行。
方式一:shell的方式:
xxxxxxxxxx
MSG=`awk '{printf("%s",$0)}' $1`if [[ $MSG =~ ^(func|fix|refactor|impr|perf|apm|chore|jvm|pom|conf|docs|style|test|typo)\(.*\):.*$ ]]then echo -e "\033[32m 提交成功! \033[0m"else echo -e "\033[31m Error: Git提交信息不符合规范 \033[0m" echo -e "\033[31m Error: 提交类型必须是[func,fix,refactor,impr,perf,apm,chore,jvm,pom,conf,docs,style,test,typo]其中之一 \033[0m" echo -e "\033[33m 举例: \n ---------------\n func(*): 新增充值厂商 \n ---------------\n fix(缴费): 缴费逻辑修正 \n ---------------\n func(service,dao): 添加礼包审核 \n\n 添加商品编辑审核状态和回调,blablablabla \n\n PRD:https://shimo.im/docs/WgxNSgWg1LoIfs5U/ \033[0m" exit 1fi方式二:python方式:
xxxxxxxxxx#!/usr/bin/env python
import sys, os, refrom subprocess import check_output
commit_msg_filepath = sys.argv[1]commit_type = sys.argv[2] if len(sys.argv) > 2 else ''branch = check_output(['git', 'symbolic-ref', '--short', 'HEAD']).strip()
print "commit_type:", commit_type
with open(commit_msg_filepath, 'r+') as f: content = f.read()
# ignore merge if content.startswith('Merge'): sys.exit(0)
result = re.match('(\w+)\(([\w+,.\-_*]+?)\): .+(.|\n)*)', content) if result is None: print "ERROR: commit msg not match pattern '<type>(<scope>): <subject>'\n\t%s" % content sys.exit(1)
sys.exit(0)然后在git仓库一级目录下执行:
xxxxxxxxxxmv commit-msg.txt .git/hooks/commit-msgchmod +x .git/hooks/commit-msg
xxxxxxxxxxmkdir -p ~/.git_template/hookscp commit-msg ~/.git_template/hooksgit config --global init.templatedir ~/.git_template.gitlab-ci.yml:
xxxxxxxxxxstageslint
commit_msgstagelintscript/bin/bash commit-msg.shonlypushescommit-msg.sh
# get commit msgif [[ $CI_COMMIT_MESSAGE ]]; then msg=$CI_COMMIT_MESSAGEelse read msg < .git/COMMIT_EDITMSGfi
echo -e "\033[33m The commit msg: \033[0m $msg"
# if the msg is merge then skip itmergePattern='^Merge 'if [[ $msg =~ $mergeCommitPattern ]]; then echo -e "\033[32m skip the merge, commit success! \033[0m" exit 0fi
# check the commit msgmaxLength=50length=${#msg}pattern='^(func|fix|refactor|impr|perf|apm|chore|jvm|pom|conf|docs|style|test|typo)\(.*\):.*$'
if [[ $msg =~ $pattern ]]; then if [[ $length -gt $maxLength ]]; then echo -e "\033[31m Error: the msg over max length \033[m" exit 1 fi echo -e "\033[32m 提交成功! \033[0m"else echo -e "\033[31m Error: Git提交信息不符合规范 \033[0m" echo -e "\033[31m Error: 提交类型必须是[func,fix,refactor,impr,perf,apm,chore,jvm,pom,conf,docs,style,test,typo]其中之一 \033[0m" echo -e "\033[33m 举例: \n ---------------\n func(*): 新增充值厂商 \n ---------------\n fix(缴费): 缴费逻辑修正 \n ---------------\n func(service,dao): 添加礼包审核 \n\n 添加商品编辑审核状态和回调,blablablabla \n\n PRD:https://shimo.im/docs/WgxNSgWg1LoIfs5U/ \033[0m" exit 1fi