悠悠楠杉
如何设置Git钩子在提交前自动运行Composer脚本
在现代PHP项目开发中,保持代码质量和一致性是团队协作和持续集成流程中的关键环节。一个常见的实践是在代码提交前自动运行代码检查(如PHPStan、Psalm)、静态分析(如PHP_CodeSniffer)以及单元测试(如PHPUnit)。手动执行这些操作不仅繁琐,还容易遗漏。通过配置Git的pre-commit钩子,我们可以在每次git commit时自动触发Composer定义的脚本,从而确保只有符合规范的代码才能进入版本控制。本文将详细介绍如何实现这一自动化机制。
Git钩子(Git Hooks)是Git提供的在特定事件发生时自动执行脚本的机制。其中,pre-commit钩子在用户执行git commit命令后、提交真正创建之前运行。如果该钩子返回非零状态码,提交将被中断,这为我们在提交前进行代码质量把关提供了绝佳机会。而Composer作为PHP生态中最主流的依赖管理工具,支持通过scripts字段定义自定义命令,例如"test": "phpunit"或"lint": "phpcs src/"。结合两者,我们可以构建一套轻量但高效的本地自动化检查体系。
首先,在项目根目录下找到.git/hooks/目录。Git默认在此提供多个示例钩子文件(如pre-commit.sample),我们需要创建一个名为pre-commit的可执行脚本。注意:这个文件必须位于.git/hooks/下,并且没有扩展名。你可以直接编辑它:
bash
vim .git/hooks/pre-commit
在文件中添加如下内容:
bash
!/bin/bash
echo "🔍 正在运行提交前检查..."
检查是否有待检测的PHP文件被修改
CHANGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '.php$')
if [ -z "$CHANGED_FILES" ]; then
echo "✅ 未检测到PHP文件变更,跳过检查。"
exit 0
fi
运行 Composer 脚本
echo "🚀 正在执行 composer lint 和 test..."
composer run lint
LINTEXITCODE=$?
composer run test
TESTEXITCODE=$?
判断执行结果
if [ $LINTEXITCODE -ne 0 ] || [ $TESTEXITCODE -ne 0 ]; then
echo "❌ 代码检查或测试失败,提交被阻止。"
exit 1
else
echo "✅ 所有检查通过,允许提交。"
exit 0
fi
上述脚本首先筛选出暂存区中被修改的PHP文件,若无则跳过检查以提升效率。接着调用composer run lint和composer run test,这两个命令需在composer.json中预先定义。例如:
json
{
"scripts": {
"lint": "phpcs --standard=PSR12 src/",
"test": "phpunit --colors=always"
}
}
你也可以根据项目需求加入PHPStan、Pest或其他工具。确保这些开发依赖已通过composer require --dev安装。
为了让钩子生效,必须赋予其可执行权限:
bash
chmod +x .git/hooks/pre-commit
此时,当你尝试提交包含不符合规范的PHP代码时,Git会中断提交流程,并输出错误信息,提示你修复问题后再提交。
虽然这种方式简单有效,但也存在局限。例如,.git/hooks/目录不会被纳入版本控制,导致每个开发者都需要手动配置钩子。为解决此问题,推荐使用cweagans/composer-patches或更合适的工具如phly/keep-a-changelog风格的钩子管理方案,或者引入lefthook、husky(通过husky-php)等第三方库来集中管理钩子并支持跨平台同步。
总而言之,利用Git的pre-commit钩子结合Composer脚本,能够在开发阶段就拦截低级错误,提升整体代码质量。这种“防御性编程”策略虽小,却能在长期维护中显著减少技术债务,是现代PHP项目不可或缺的一环。
