引言:为什么我们需要代码提交前的「安全检查」?
作为开发者,你有没有遇到过这些情况?
- 不小心把调试代码提交到了远程仓库
- 代码格式混乱导致团队协作出现分歧
- 因为一个简单的语法错误,CI/CD 流水线反复失败
- 甚至无意中把敏感信息(如密钥)推送到了公开仓库
这些看似小问题,却常常浪费团队大量时间和精力。今天我们要聊的 pre-commit 工具,就是解决这些问题的「代码提交守门员」。
一、pre-commit 是什么?它如何保护你的代码质量?
理解 pre-commit 的核心概念
pre-commit 是一个 Git 钩子管理工具,它能在你执行 git commit 命令时,自动运行一系列检查脚本,只有通过这些检查,代码才能被成功提交。
简单来说,它就像是你代码提交前的一道「安检门」,帮助你在代码进入版本控制系统前就发现并解决潜在问题。
pre-commit 的工作原理
它利用 Git 的 pre-commit 钩子机制,在代码提交前拦截操作,运行配置好的检查项(如代码格式化、语法检查、静态分析等),帮助开发者在本地就发现并解决问题。
具体流程是这样的:
- 你执行 git commit 命令
- pre-commit 钩子被触发
- pre-commit 工具运行你配置的所有检查项
- 如果所有检查都通过,commit 操作继续执行
- 如果有任何检查失败,commit 操作被中止,你需要修复问题后重新提交
使用 pre-commit 的三大好处
- 提前发现问题:在代码进入远程仓库前就解决大多数质量问题,避免把问题带入后续流程
- 统一团队规范:确保所有提交的代码都符合团队约定的标准,减少代码审查时关于格式的讨论
- 减少 CI/CD 失败:避免因低级错误导致的流水线反复构建,提高开发效率
二、如何在 Windows 下快速上手 pre-commit?
安装 pre-commit(Windows 版本)
在 Windows 系统上安装 pre-commit 非常简单,只需要几个步骤:
- 确保已安装 Python pre-commit 是一个 Python 工具,所以首先需要确保你的系统上已经安装了 Python。你可以通过在命令提示符(CMD)或 PowerShell 中运行以下命令来检查:
python --version
如果没有安装 Python,可以访问 Python 官方网站 下载最新版本的安装包,并在安装时勾选「Add Python to PATH」选项。
- 使用 pip 安装 pre-commit 打开命令提示符(CMD)或 PowerShell,运行以下命令:
pip install pre-commit
- 验证安装是否成功 安装完成后,运行以下命令来验证:
pre-commit --version
如果能看到版本号信息,说明 pre-commit 已经成功安装。
创建并配置 pre-commit 配置文件
- 初始化 pre-commit 进入你的 Git 项目目录,在命令提示符或 PowerShell 中运行:
pre-commit install
这个命令会在你的项目的 .git/hooks 目录下创建 pre-commit 钩子脚本。
- 创建配置文件
在项目根目录下创建一个名为
.pre-commit-config.yaml的文件。这是 pre-commit 的核心配置文件,用于定义要运行的检查项。
一个简单的配置文件示例:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- 理解配置文件结构
repos:包含一个或多个 Git 仓库,这些仓库提供 pre-commit 钩子repo:钩子仓库的 URLrev:要使用的钩子仓库版本hooks:要使用的钩子列表id:钩子的唯一标识符
常用的 pre-commit 钩子推荐
以下是一些在日常开发中非常实用的 pre-commit 钩子:
通用检查类
- trailing-whitespace:删除行尾的空白字符
- end-of-file-fixer:确保文件以换行符结尾
- check-yaml:检查 YAML 文件的语法是否正确
- check-added-large-files:避免意外将大文件引入到仓库
代码格式化类
black:自动格式化 Python 代码,确保代码风格一致
black 是一个 Python 代码格式化工具,它的主要功能是自动格式化 Python 代码,确保代码风格一致。 注意black只能修复代码中的格式问题,不能修复代码中的语法错误。
安装依赖:
pip install black==23.3.0
pre-commit 配置如下:
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
isort:自动排序 Python 导入语句
isort 用于自动排序和格式化 Python 文件中的导入语句。它的主要功能包括:
- 分类导入:自动将导入分为三类
- 标准库导入
- 第三方库导入
- 本地模块导入
- 字母排序 :在每个类别内按字母顺序排序导入
- 格式化 :处理导入的格式,如合并相同模块的导入
安装依赖:
pip install isort==5.12.0
运行isort:
# 检查并修改导入语句
isort HelloWorld.py
# 检查但不修改
isort --check HelloWorld.py
pre-commit 配置如下:
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
语法检查类
flake8:检查 Python 代码中的语法错误和风格问题
flake8 主要是一个代码质量检查工具,它的核心功能是检测代码中的语法错误、编码规范问题、潜在的逻辑问题和代码质量问题,但不提供自动修复这些问题的能力。 注意:
- 若有语法错误,flake8 会报告错误位置和类型,并停止后续检测,因此报告语法错误时可能还有其他未检测到的问题。
- 如果风格问题已经被black修复,flake8就不会再报告这些问题了,因此推荐将black和flake8结合使用,使用时要注意先后顺序。
安装依赖:
pip install flake8==6.0.0
检测语法和代码风格:
# 检测 flake8_test.py 中的语法错误和风格问题
flake8 flake8_test.py
# --show-source 显示错误的代码位置
flake8 --show-source flake8_test.py
pre-commit 配置如下:
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
安全检查类
detect-secrets:检测代码中是否包含敏感信息(如 API 密钥、密码等)
detect-secrets 是 Yelp 开发的一个工具,用于扫描代码仓库中可能包含的敏感信息,如 API 密钥、密码、证书等。它使用多种启发式规则来识别潜在的敏感信息,并可以帮助团队避免将敏感信息意外提交到代码仓库中。
注意:它不是 100% 准确的,可能会产生误报或漏报,因此仍然需要人工审查。
安装依赖:
pip install detect-secrets==1.5.0
检测敏感信息:
detect-secrets scan
当运行 pre-commit run detect-secrets --all-files 时,如果检测到大量敏感信息(尤其是在 lock 文件中),这是正常现象,因为这些文件通常包含许多看起来像敏感信息的高熵字符串。
解决方法:
- 跳过 lock 文件
- 添加基线文件
跳过 lock 文件
- 可以使用
--exclude-files参数来排除特定文件
detect-secrets scan --exclude-files "package-lock.json|pnpm-lock.yaml|yarn.lock"
- 在 .pre-commit-config.yaml 中有两种方式:
- 添加排除规则,跳过 lock 文件
- 使用--exclude-files参数来排除特定文件
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
# 跳过lock文件,因为它们通常包含大量看起来像敏感信息的高熵字符串
exclude: |
(?x)^(
package-lock.json|
pnpm-lock.yaml|
yarn.lock
)$
# 也可以使用--exclude-files参数来排除特定文件
args: [--exclude-files, "package-lock.json|pnpm-lock.yaml|yarn.lock"]
添加基线文件
- 初始化基线文件(baseline),记录当前已知的敏感信息,这样后续的检查只会关注新添加的敏感信息:
# 扫描当前目录下所有被Git跟踪的文件
detect-secrets scan > .secrets.baseline
# 扫描当前目录下 所有文件 ,包括未被Git跟踪的文件
detect-secrets scan --all > .secrets.baseline
- 将当前代码状态与已有的基线文件进行比较,检测是否引入了新的敏感信息:
detect-secrets scan --baseline .secrets.baseline
- 在
.pre-commit-config.yaml中为detect-secrets钩子添加参数,指定使用这个 baseline 文件:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: [--baseline, .secrets.baseline]
这样,pre-commit 就只会报告 baseline 文件中未记录的新敏感信息,避免每次运行都报告大量已知的误报,不仅仅是 lock 文件,其他已知的敏感信息也会过滤不再报告。
三、pre-commit 的进阶技巧与最佳实践
在团队中推广 pre-commit
当你在个人项目中尝到 pre-commit 的甜头后,可能会想要在团队中推广它。以下是一些实用的推广技巧:
-
在项目 README 中添加 pre-commit 安装指南,确保新成员能够快速上手
-
将 pre-commit 配置纳入版本控制,确保团队成员使用相同的配置
-
在 CI/CD 流程中强制执行 pre-commit 检查,可以使用
pre-commit run --all-files命令 -
定期更新钩子版本,以获取最新的功能和修复
开发自定义 pre-commit 钩子
当现成的钩子不能满足你的特定需求时,你可以开发自己的 pre-commit 钩子。以下是创建自定义钩子的基本步骤:
-
创建一个简单的脚本,该脚本将执行你想要的检查逻辑
-
确保脚本具有执行权限(在 Windows 上这一步通常不是必需的)
-
在
.pre-commit-config.yaml中添加自定义钩子:- repo: local hooks: - id: my-custom-hook name: My Custom Hook entry: path/to/your/script.py language: python types: [python]
与 CI/CD 流程结合
为了确保代码质量,最好在 CI/CD 流程中也运行 pre-commit 检查。这样可以避免有人绕过本地检查直接提交代码。
在 CI/CD 配置文件中,你可以添加类似以下的步骤:
jobs:
lint:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install pre-commit
run: pip install pre-commit
- name: Run pre-commit checks
run: pre-commit run --all-files
结论:让 pre-commit 成为你的代码质量「第一道防线」
pre-commit 不是一个复杂的工具,但它能为你的项目带来显著的质量提升。通过在代码提交前就解决掉大多数常见问题,你和你的团队可以把更多精力放在真正重要的功能开发上。
无论是个人项目还是大型团队协作,pre-commit 都值得尝试——它可能不会解决所有代码质量问题,但绝对能帮你避免大多数低级错误。
现在就给你的项目加上这道「安全门」吧!打开命令提示符或 PowerShell,按照本文的指南安装 pre-commit,让你的代码提交更有保障。