有些编程语言提供了代码格式化检查等工具,如:Go、Rust等,我们可以在commit之前,对代码进行格式化检查,保证代码规范,而pre-commit正是这样的工具;
在Git项目中增加pre-commit校验
pre-commit 概述
pre-commit官方网站:
pre-commit支持的功能有:
- 只需要提供配置文件地址,自动从中央hooks仓库获取脚本(如果有多个项目,就不需要再每个项目都拷贝一份hooks了);
- 可以定义本地脚本仓库,允许开发人员自定义脚本,且无需修改配置文件:
- 每个阶段允许定义多个脚本:
- 多个脚本可以使得功能划分而无需整合到一个臃肿的文件中;
- 脚本支持多种语言
需要注意的是:
pre-commit这个工具不仅仅可以在pre-commit阶段执行,其实可以在git-hooks的任意阶段;
安装pre-commit
在系统中安装pre-commit
1 | brew install pre-commit |
在项目中安装pre-commit
除了需要在系统中安装pre-commit,还需要在Git项目中安装:
1 | cd <git-repo> |
上面的操作将会在项目的.git/hooks下生成一个pre-commit文件(覆盖原pre-commit文件),该hook会根据项目根目录下的.pre-commit-config.yaml执行任务;
如果
vim .git/hooks/pre-commit可以看到代码的实现,基本逻辑是利用pre-commit文件去拓展更多的pre-commit;
安装/卸载其他阶段的hook:
1 | pre-commit install |
常用指令
1 | # 手动对所有的文件执行hooks,新增hook的时候可以执行,使得代码均符合规范。直接执行该指令则无需等到pre-commit阶段再触发hooks |
更多指令及指令参数请直接访问pre-commit官方网站;
添加第三方hooks
在Git仓库初始化pre-commit:
1 | cd <git-repo> |
如下为一个基本的配置样例:
.pre-commit-config.yaml
1 | # 该config文件为该项目的pre-commit的配置文件,用于指定该项目可以执行的git hooks |
上面我们引入了两个配置:
- https://github.com/pre-commit/pre-commit-hooks
- https://github.com/macisamuele/language-formatters-pre-commit-hooks
在run之后,pre-commit会下载指定仓库代码,并安装配置所需要的运行环境;
配置完成之后可以通过pre-commit run --all-files运行一下添加的hooks;
下表为.pre-commit-hooks.yaml可选配置项:
| key word | description |
|---|---|
id |
the id of the hook - used in pre-commit-config.yaml. |
name |
the name of the hook - shown during hook execution. |
entry |
the entry point - the executable to run. entry can also contain arguments that will not be overridden such as entry: autopep8 -i. |
language |
the language of the hook - tells pre-commit how to install the hook. |
files |
(optional: default '') the pattern of files to run on. |
exclude |
(optional: default ^$) exclude files that were matched by files |
types |
(optional: default [file]) list of file types to run on (AND). See Filtering files with types. |
types_or |
(optional: default []) list of file types to run on (OR). See Filtering files with types. new in 2.9.0. |
exclude_types |
(optional: default []) the pattern of files to exclude. |
always_run |
(optional: default false) if true this hook will run even if there are no matching files. |
verbose |
(optional) if true, forces the output of the hook to be printed even when the hook passes. new in 1.6.0. |
pass_filenames |
(optional: default true) if false no filenames will be passed to the hook. |
require_serial |
(optional: default false) if true this hook will execute using a single process instead of in parallel. new in 1.13.0. |
description |
(optional: default '') description of the hook. used for metadata purposes only. |
language_version |
(optional: default default) see Overriding language version. |
minimum_pre_commit_version |
(optional: default '0') allows one to indicate a minimum compatible pre-commit version. |
args |
(optional: default []) list of additional parameters to pass to the hook. |
stages |
(optional: default (all stages)) confines the hook to the commit, merge-commit, push, prepare-commit-msg, commit-msg, post-checkout, post-commit, post-merge, or manual stage. See Confining hooks to run at certain stages. |
关于开发hooks仓库:
本地hooks
pre-commit 也提供了local的hook,允许在entry中配置执行指令或指向本地一个可执行的脚本文件,使用起来和husky类似;
- 脚本与代码仓库紧密耦合,并且与代码仓库一起分发;
- Hooks需要的状态只存在于代码仓库的build artifact中(比如应用程序的pylint的virtualenv);
- linter的官方代码仓库没有提供pre-commit metadata;
local hooks可以使用支持additional_dependencies 的语言或者 docker_image / fail / pygrep / script / system;
在使用时,需要定义
repo: local,即:本地仓库;
例如:
1 | # 定义repo为local,表示该repo为本地仓库 |
上面给hooks定义了两个步骤:
- pylint
- changelogs-rst
几配置例子
Rust项目
https://github.com/JasonkayZK/rust-learn/blob/main/.pre-commit-config.yaml
1 | repos: |
Go项目
https://github.com/JasonkayZK/Go_Learn/blob/master/.pre-commit-config.yaml
1 | repos: |
附录
文章参考: