• 手写 git hooks 脚本(pre-commit、commit-msg)实现代码规范校验+Git提交日志校验


    创建脚本文件

    init-dev.sh文件位置放在根目录下。

    #!/bin/bash
    set -e
    echo '*******************************************'
    echo '***********此脚本用于开发代码时使用************'
    echo '*******************************************'
    
    #拉取代码后先执行此文件
    if [[ ! -e ".git/hooks/pre-commit" ]]; then
      echo "初始化checkstyle基础配置"
    else
      echo "更新checkstyle基础配置"
      rm -rf .git/hooks/commit-msg
      rm -rf .git/hooks/pre-commit
    fi
    
    cp ./checkstyle/commit-msg .git/hooks
    cp ./checkstyle/pre-commit .git/hooks
    chmod 700 .git/hooks/*
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    项目根目录下创建checkstyle文件夹

    文件夹下分别存放以下文件。
    在这里插入图片描述

    checkstyle-9.3-all.jar

    checkstyle-9.3-all.jar自行去官网下载,传送链
    在这里插入图片描述

    sun_checks.xml

    sun_checks.xml内容如下,可以按需调整:

    
    DOCTYPE module PUBLIC
    		"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
    		"https://checkstyle.org/dtds/configuration_1_3.dtd">
    
    
    
    <module name="Checker">
    	
    	<property name="severity" value="error"/>
    
    	<property name="fileExtensions" value="java, properties, xml"/>
    
    	
    	
    	<module name="BeforeExecutionExclusionFileFilter">
    		<property name="fileNamePattern" value="module\-info\.java$"/>
    	module>
    
    	
    	<module name="SuppressionFilter">
    		<property name="file" value="${org.checkstyle.sun.suppressionfilter.config}"
    				  default="checkstyle-suppressions.xml" />
    		<property name="optional" value="true"/>
    	module>
    
    	
    	
    
    	
    	
    	
    	<module name="NewlineAtEndOfFile"/>
    
    	
    	
    	<module name="Translation"/>
    
    	
    	
    	
    	<module name="FileLength"/>
    	
    	<module name="LineLength">
    		<property name="max" value="300"/>
    		<property name="fileExtensions" value="java"/>
    	module>
    
    	
    	
    	
    
    	
    	
    	
    	
    	
    	
    	
    	
    
    	
    	
    	
    	
    	
    	
    
    	<module name="TreeWalker">
    
    		
    		
    		<module name="InvalidJavadocPosition"/>
    		<module name="JavadocMethod">
    			<property name="allowMissingReturnTag" value="true"/>
    		module>
    		<module name="JavadocType">
    			<property name="allowUnknownTags" value="true"/>
    		module>
    		
    		<module name="JavadocVariable">
    			
    			<property name='ignoreNamePattern' value='.*Business|.*Service|.*Handler|.*Mapper|.*Encoder|.*ENCODER|.*Properties|.*Listener|.*Map|.*Manager|.*Template|.*Client|.*Util.*|LOG|LOGGER'/>
    		module>
    		
    		<module name="JavadocStyle">
    			
    			<property name='checkFirstSentence' value='false'/>
    			<property name='checkEmptyJavadoc' value='true'/>
    		module>
    		
    		<module name="MissingJavadocMethod"/>
    
    		
    		
    		<module name="ConstantName"/>
    		<module name="LocalFinalVariableName"/>
    		<module name="LocalVariableName"/>
    		<module name="MemberName"/>
    		<module name="MethodName"/>
    		
    		<module name="PackageName">
    			<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
    			<message key="name.invalidPattern" value="包名 ''{0}'' 要符合 ''{1}''格式."/>
    		module>
    		<module name="ParameterName"/>
    		<module name="StaticVariableName"/>
    		
    		<module name="TypeName">
    			<property name="severity" value="warning"/>
    			<message key="name.invalidPattern" value="名称 ''{0}'' 要符合 ''{1}''格式."/>
    		module>
    
    		
    		
    		
    		<module name="AvoidStarImport">
    			<property name="allowClassImports" value="true"/>
    		module>
    		
    		<module name="IllegalImport"/> 
    		
    		<module name="RedundantImport"/>
    		
    		<module name="UnusedImports">
    			<property name="processJavadoc" value="false"/>
    		module>
    
    		
    		
    		
    		<module name="MethodLength">
    			<property name="tokens" value="METHOD_DEF"/>
    			<property name="max" value="300"/>
    		module>
    		<module name="ParameterNumber"/>
    
    		
    		
    		<module name="EmptyForIteratorPad"/>
    		<module name="GenericWhitespace"/>
    		<module name="MethodParamPad"/>
    		<module name="NoWhitespaceAfter"/>
    		<module name="NoWhitespaceBefore"/>
    		<module name="OperatorWrap"/>
    		<module name="ParenPad"/>
    		<module name="TypecastParenPad"/>
    		<module name="WhitespaceAfter"/>
    		<module name="WhitespaceAround"/>
    
    		
    		
    		<module name="ModifierOrder"/>
    		<module name="RedundantModifier"/>
    
    		
    		
    		
    		<module name="AvoidNestedBlocks">
    			<property name="allowInSwitchCase" value="true"/>
    		module>
    		<module name="EmptyBlock"/>
    		<module name="LeftCurly"/>
    		<module name="NeedBraces"/>
    		<module name="RightCurly"/>
    
    		
    		
    		<module name="EmptyStatement"/>
    		<module name="EqualsHashCode"/>
    		
    		<module name="HiddenField">
    			<property name="tokens" value="VARIABLE_DEF"/>
    		module>
    		<module name="IllegalInstantiation"/>
    		<module name="InnerAssignment"/>
    		
    		<module name="MissingSwitchDefault"/>
    		<module name="MultipleVariableDeclarations"/>
    		<module name="SimplifyBooleanExpression"/>
    		<module name="SimplifyBooleanReturn"/>
    
    		
    		
    		
    		<module name="FinalClass"/>
    		
    		<module name="InterfaceIsType"/>
    		<module name="VisibilityModifier"/>
    
    		
    		
    		<module name="ArrayTypeStyle"/>
    		
    
    		<module name="TodoComment"/>
    		<module name="UpperEll"/>
    
    		
    		<module name="SuppressionXpathFilter">
    			<property name="file" value="${org.checkstyle.sun.suppressionxpathfilter.config}"
    					  default="checkstyle-xpath-suppressions.xml" />
    			<property name="optional" value="true"/>
    		module>
    
    		
    		<module name="Regexp">
    			<property name="format" value=".printStackTrace"/>
    			<property name="illegalPattern" value="true"/>
    		module>
    		<module name="Regexp">
    			<property name="format" value="System.out.println"/>
    			<property name="illegalPattern" value="true"/>
    		module>
    
    		
    		<module name="TrailingComment"/>
    		
    		<module name="TodoComment"/>
    		
    		<module name="UncommentedMain">
    			<property name="excludedClasses" value=".*[Application,Test]$"/>
    		module>
    
    	module>
    
    module>
    
    • 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
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259

    pre-commit

    pre-commit文件内容如下,可以配置具体的项目代码位置,或者仅扫描提交的代码。

    #!/bin/sh
    echo '*******************************************'
    echo '***************强制检查代码规范***************'
    echo '****参考:Checkstyle代码规范检查使用教程.md****'
    echo '*******************************************'
    
    #指定路径扫描
    #java -jar checkstyle/checkstyle-9.3-all.jar -c checkstyle/sun_checks.xml abc-modules/abc-upms-biz/src
    
    #每次扫描仅对当前提交的内容来扫
    #java -jar checkstyle/checkstyle-9.3-all.jar  -c checkstyle/sun_checks.xml $(git diff --cached --name-only --diff-filter=ACM -- '*.java')
    java -jar checkstyle/checkstyle-9.3-all.jar  -c checkstyle/sun_checks.xml $(git diff --cached --name-only --diff-filter=ACM -- '*')
    
    
    exitCode="$?"
    exit $exitCode
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    commit-msg

    commit-msg的内容如下:

    #!/bin/sh
    echo '*******************************************'
    echo '********强制检查git commit msg提交格式********'
    echo '******提交格式参考文档:Git提交日志规范.md******'
    echo '*******************************************'
    
    # 用 `` 可以将命令的输出结果赋值给变量
    # 获取当前提交的 commit msg
    commit_msg=`cat $1`
    
    # 获取用户 email
    email=`git config user.email`
    msg_re="^(feat|fix|docs|style|refactor|perf|test|workflow|build|ci|chore|release|workflow)(\(.+\))?: .{1,100}"
    
    if [[ ! $commit_msg =~ $msg_re ]]
    then
    	echo "\n不合法的 commit 消息提交格式,请使用正确的格式:\
    	\nfeat: add comments\
    	\nfix: handle events on blur (close #28)\
    	\n详情请查看 git commit 提交规范:https://github.com/woai3c/Front-end-articles/blob/master/git%20commit%20style.md"
    
    	# 异常退出
    	exit 1
    fi
    
    
    # 对用户权限做判断则比较简单,只需要检查用户的邮箱或用户名就可以了(假设现在只有 abc 公司的员工才有权限提交代码)。
    #email_re="@abc\.com"
    #if [[ ! $email =~ $email_re ]]
    #then
    #	echo "此用户没有权限,具有权限的用户为: xxx@abc.com"
    #
    #	# 异常退出
    #	exit 1
    #fi
    
    
    • 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

    以上配置完成之后,执行脚本init-dev.sh初始化配置即可生效,之后在提交代码时,就可以针对代码规范进行检查、针对Git提交的msg信息格式进行检查。

    sh init-dev.sh
    
    • 1

    以下是Git提交日志的规范:

    Git提交日志规范

    提交代码时,如果不能形成有效约束,依靠个人的自觉,这样即使每个人是积极的状态,但是每个人的知识构成不同,也会造成提交风格迥异。

    commit-message规范必要性

    1. 统一格式的提交记录,更清晰和易读
    2. 可以通过提交记录来了解本次提交的目的,更好的CR和重构
    3. 更容易了解变更,定位和发现问题
    4. 每个提交描述都是经过思考的,改善提交质量
    5. 生成变更记录

    git commit 提交规范

    (): 
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    大致分为三个部分(使用空行分割):

    1. 标题行: 必填, 描述主要修改类型和内容
    2. 主题内容: 描述为什么修改, 做了什么样的修改, 以及开发的思路等等
    3. 页脚注释: 放 Breaking Changes 或 Closed Issues

    type

    commit 的类型:

    • feat: 新功能、新特性
    • fix: 修改 bug
    • perf: 更改代码,以提高性能(在不影响代码内部行为的前提下,对程序性能进行优化)
    • refactor: 代码重构(重构,在不影响代码内部行为、功能下的代码修改)
    • docs: 文档修改
    • style: 代码格式修改, 注意不是 css 修改(例如分号修改)
    • test: 测试用例新增、修改
    • build: 影响项目构建或依赖项修改
    • revert: 恢复上一次提交
    • ci: 持续集成相关文件修改
    • chore: 其他修改(不在上述类型中的修改)
    • release: 发布新版本

    scope

    commit 影响的范围, 比如: route, component, utils, build…

    subject

    commit 的概述

    body

    commit 具体修改内容, 可以分为多行.

    footer

    一些备注, 通常是 BREAKING CHANGE 或修复的 bug 的链接.

    约定式提交规范

    以下内容来源于:https://www.conventionalcommits.org/zh-hans/v1.0.0-beta.4/

    • 每个提交都必须使用类型字段前缀,它由一个名词组成,诸如 featfix ,其后接一个可选的作用域字段,以及一个必要的冒号(英文半角)和空格。
    • 当一个提交为应用或类库实现了新特性时,必须使用 feat 类型。
    • 当一个提交为应用修复了 bug 时,必须使用 fix 类型。
    • 作用域字段可以跟随在类型字段后面。作用域必须是一个描述某部分代码的名词,并用圆括号包围,例如: fix(parser):
    • 描述字段必须紧接在类型/作用域前缀的空格之后。描述指的是对代码变更的简短总结,例如: fix: array parsing issue when multiple spaces were contained in string.
    • 在简短描述之后,可以编写更长的提交正文,为代码变更提供额外的上下文信息。正文必须起始于描述字段结束的一个空行后。
    • 在正文结束的一个空行之后,可以编写一行或多行脚注。脚注必须包含关于提交的元信息,例如:关联的合并请求、Reviewer、破坏性变更,每条元信息一行。
    • 破坏性变更必须标示在正文区域最开始处,或脚注区域中某一行的开始。一个破坏性变更必须包含大写的文本 BREAKING CHANGE,后面紧跟冒号和空格。
    • BREAKING CHANGE: 之后必须提供描述,以描述对 API 的变更。例如: BREAKING CHANGE: environment variables now take precedence over config files.
    • 在提交说明中,可以使用 featfix 之外的类型。
    • 工具的实现必须不区分大小写地解析构成约定式提交的信息单元,只有 BREAKING CHANGE 必须是大写的。
    • 可以在类型/作用域前缀之后,: 之前,附加 ! 字符,以进一步提醒注意破坏性变更。当有 ! 前缀时,正文或脚注内必须包含 BREAKING CHANGE: description

    示例

    fix

    如果修复的这个BUG只影响当前修改的文件,可不加范围。如果影响的范围比较大,要加上范围描述。

    例如这次 BUG 修复影响到全局,可以加个 global。如果影响的是某个目录或某个功能,可以加上该目录的路径,或者对应的功能名称。

    // 示例1
    fix(global): 修复checkbox不能复选的问题
    // 示例2 下面圆括号里的 common 为通用管理的名称
    fix(common): 修复字体过小的BUG,将通用管理下所有页面的默认字体大小修改为 14px
    // 示例3
    fix: value.length -> values.length
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    feat

    feat: 添加网站主页静态页面
    
    这是一个示例,假设对点检任务静态页面进行了一些描述。
     
    这里是备注,可以是放BUG链接或者一些重要性的东西。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    chore

    chore 的中文翻译为日常事务、例行工作,顾名思义,即不在其他 commit 类型中的修改,都可以用 chore 表示。

    chore: 将表格中的查看详情改为详情
    
    • 1

    参考资料

  • 相关阅读:
    大屏大概是怎么个开发法(前端)
    抖音背后的视频体验分析体系与优化技术揭秘
    c# 实现定义一套中间SQL可以跨库执行的SQL语句
    Android组件化开发,其实就这么简单
    23.09.05内网盲区记录
    C语言练习百题之9的次数
    uniapp实现相册、拍照及视频录制功能
    24校招总结
    C语言源代码系列-管理系统之学生信息管理系统
    2022-07-15 第六组 润土 Java03数据结构学习笔记
  • 原文地址:https://blog.csdn.net/u011019141/article/details/126565758