当我们需要对 Git 提交的相关内容做校验时,可以使用客户端的 commit-msg 钩子。
commit-msg 钩子
前文我们使用 pre-receive
在 Gitlab
服务器做 Commit
提交信息校验,这么做的好处是可以作用于全局,可以让所有的提交都规范,如果我们公司或者组织没有这个要求,就想自己去约束自己呢,那就直接在客户端侧去实现.
具体详情可以参阅官网:这里
实施步骤
开始前,我们必须跟业务侧约定好 commit
信息的规范,同时设计好钩子的作用范围,本文只针对单个项目起作用。
前提条件
commit message 要规范:
格式:<类型>[可选的作用域]:# <描述>
实现原理
hooks
钩子会收到1个参数,此参数是存有当前提交信息的临时文件的路径。如果该钩子脚本以非零值退出,Git
将放弃提交,因此,可以用来在提交通过前验证项目状态或提交信息。
Git 的 工作流程如下:
Git 流程图
编码
新建 commit-msg 目录,新建 main.go 文件,复制以下代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package main
import (
"fmt"
"os"
"os/exec"
"regexp"
"strings"
)
type CommitType string
const (
CommitMessagePattern = `((feat|fix|to|docs|style|refactor|perf|test|chore|revert|merge|sync|build|ci)(\()(\s|\S){0,}(\)):(\s)*#(\s|\S)+(\s)(\s|\S)+)|^Merge\ (.*)`
checkFailedMeassge = `GL-HOOK-ERR:##############################################################################
GL-HOOK-ERR:##
GL-HOOK-ERR:## Commit message style check failed!
GL-HOOK-ERR:##
GL-HOOK-ERR:## Commit message style must satisfy this regular:
GL-HOOK-ERR:## 类型(可选的作用域):#Jira_ID 描述
GL-HOOK-ERR:##
GL-HOOK-ERR:## Example:
GL-HOOK-ERR:## fix(DAO):#JIRA-001 用户查询缺少username属性
GL-HOOK-ERR:##
GL-HOOK-ERR:##############################################################################` )
var commitMsgReg = regexp . MustCompile ( CommitMessagePattern )
func main () {
// 获取第一个参数 $1
param := os . Args [ 1 ]
commitMsg := getCommitMsg ( param )
commitTypes := commitMsgReg . FindAllStringSubmatch ( commitMsg , - 1 )
if len ( commitTypes ) != 1 {
// 打印异常commit message
commitMessagePrint ( commitMsg )
// 退出并打印规范提示
checkFailed ()
} else {
fmt . Println ( " " )
}
}
// 获取git commit 信息,去掉换行符
func getCommitMsg ( CommitMessage string ) string {
cmd := fmt . Sprintf ( "cat %s |head -n 1" , CommitMessage )
getCommitMsgCmd := exec . Command ( "bash" , "-c" , cmd )
getCommitMsgCmd . Stdin = os . Stdin
getCommitMsgCmd . Stderr = os . Stderr
b , err := getCommitMsgCmd . Output ()
if err != nil {
fmt . Print ( err )
os . Exit ( 1 )
}
commitMsg := Strip ( string ( b ))
return commitMsg
}
func checkFailed () {
fmt . Fprintln ( os . Stderr , checkFailedMeassge )
os . Exit ( 1 )
}
// 打印message信息
func commitMessagePrint ( message string ) {
fmt . Fprintln ( os . Stderr , "GL-HOOK-ERR:##" + " " + "错误的 commit message: " + message )
}
// 去除换行空格
func Strip ( s string ) ( r string ) {
if s != " " {
s = strings . Trim ( s , " " )
s = strings . Trim ( s , "\t" )
s = strings . Trim ( s , "\n" )
r = strings . Trim ( s , "\r" )
}
return
}
使用方法
假设你本地已经装好了 golang,然后设置 go module 模式
如果你是 windows 系统,需要交叉编译得先设置 go env -w GOOS=linux
1
2
3
4
5
6
7
8
cd commit-msg
go env -w CGO_ENABLED = 0
go env -w GO111MODULE = on
go env -w GOARCH = amd64
go env -w GOOS = linux
go mod init commit-msg
go mod tidy
go build -ldflags= "-w"
把编译后的文件丢进项目的 .git/hooks 目录 并给与可执行权限,即可。