git 注释提交规范检查

235 阅读3分钟

关于提交日志规范

良好的 Commit Message 有利于代码审查,能更快速查找变更记录,并且可以直接生成 Change log

规范代码提交有很多种,这里介绍一种 angular 的规范写法:

Commit Message 的写法规范:conventional-changelog

<type>(<scope>): <subject>
<空行>
<body>
<空行>
<footer>

日志第一行要求必须填写,bodyfooter 可选填。

Header填写

Type

type 填写 commit 的类别。 允许填写以下几种类型:

注:这里我认为可以根据团队需要增加一些类型,整个团队遵循一个约定即可

feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
test:增加测试用例等
chore:构建过程或辅助工具的变动
modify:非功能性的小的改动
debug:提交了一些测试用的代码

Scope

commit的影响范围,比如会影响到哪个模块/性能/哪一层(业务层,持久层,缓存,rpc),如果是特性代码,可以写特性名称

Subject

commit的简短描述,不超过50个字符

  • 使用现在式,祈使句
  • 第一个字母无需大写
  • 结尾不用加句号
  • 可以使用中文描述

Body

subject 一样,使用现在式,祈使句。应该说明提交代码的动机,以及跟前一个版本的对比。

Footer

可填写:

  • 描述重大变更的信息
  • 关闭某个项目任务/关闭 Issue

特殊情况

  • fixupfixup! 开头的日志跳过上述规则检查,号后面需要接一个空格。 当我们一个分支上面有多个提交,且部分提交是为了弥补之前的提交所做的细微改动。这个时候可以使用fixup将这些细微的提交合并(被合并掉的提交的message将被删除),这样我们主分支的git log graph看起来就更加干净

  • squashsquash! 开头的日志跳过上述规则检查,号后面需要接一个空格。 将多个commit合并为一个commit进行提交时,日志以 squash! 开头。

  • revertrevert: 开头的日志跳过上述规则检查,号后面需要接一个空格。 撤销某项commit时,日志要求以 revert 开头

检测方式

以下是一段 python 检测的参考代码,可以通过添加到 gitlab 中的 hooks 目录进行 commit 预检测 /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/

#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys,os,re

# 检查正则表达式
def checkVaild(commit_str):
    type_list = ['fix','feat','modify','refactor','docs','style','test','chore','debug']
    # 这几种提交跳过检查
    # const FIXUP_PREFIX_RE = /^fixup! /i;
    # const SQUASH_PREFIX_RE = /^squash! /i;
    # const REVERT_PREFIX_RE = /^revert:? /i;
    if re.search(r'^fixup! ', commit_str, re.I) :
        return True
    if re.search(r'^squash! ', commit_str, re.I) :
        return True
    if re.search(r'^revert:? ', commit_str, re.I) :
        return True
    preg_rule = re.compile(r'^(?:fixup!\s*)?(\w+)(?:\(([^)]+)\))?\: (.+)$')
    match_rs = re.findall(preg_rule, commit_str)
    if len(match_rs)<1 :
        return False
    if match_rs[0][0] not in type_list :
        return False
    return True

# 读取git日志内容
def getGitLog(sign1,sign2):
    commit_message = os.popen('git log ' + sign1 + '..' + sign2 + ' --pretty=format:%s').read()
    return commit_message

# 运行主题
def mainRun():
    line = sys.stdin.readline().strip('\n')
    line_input = line.split()
    if len(line_input)<2 :
        sys.exit(0);
    # 删除分支时正常退出
    if (line_input[0] == "0000000000000000000000000000000000000000" \
        or line_input[1] == "0000000000000000000000000000000000000000") :
        sys.exit(0);

    commit_message = getGitLog(line_input[0], line_input[1])
    if commit_message=='' :
        print('can not find any commit message!')
    commit_g = commit_message.split('\n')
    for commit in commit_g :
        if not(checkVaild(commit)) :
            print('your commit message is invaild!' + '[' + commit + ']')
        else :
            print('well format ' + '[' + commit + ']')


warning_info = '''##############################################################
##                                                          ##
## Commit message style check !                             ##
##                                                          ##
## Commit message style must satisfy this regular:          ##
##   ^(?:fixup!\s*)?(\w+)(?:\(([^)]+)\))?\: (.+)$           ##
##                                                          ##
## Example:                                                 ##
##   feat(test): test commit style check.                   ##
##                                                          ##
## You should use follow type:                              ##
## fix,feat,modify,refactor,docs,style,test,chore,debug     ##
##                                                          ##
##############################################################
规则文档:XXX'''


print(warning_info)

mainRun()