本文目录导读:

我来详细介绍如何配置 PHP 项目的 Git 钩子:
Git 钩子基础
钩子目录位置
# 进入项目目录 cd /path/to/your/php-project # 查看钩子目录 ls .git/hooks/
常用 PHP 项目钩子配置
1 Pre-commit 钩子(提交前检查)
文件:.git/hooks/pre-commit
#!/bin/bash
# PHP 语法检查
echo "Running PHP syntax check..."
ERROR=0
# 检查即将提交的 PHP 文件
for file in $(git diff --cached --name-only --diff-filter=ACM | grep '\.php$'); do
if [ -f "$file" ]; then
if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then
echo "PHP Syntax Error in: $file"
php -l "$file"
ERROR=1
fi
fi
done
# 运行 PHP_CodeSniffer 代码规范检查
if command -v phpcs &> /dev/null; then
echo "Running PHP CodeSniffer..."
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.php$')
if [ ! -z "$FILES" ]; then
if ! phpcs --standard=PSR2 $FILES; then
echo "PHP Code Standards Error"
ERROR=1
fi
fi
fi
# 运行单元测试(可选)
if [ "$ERROR" -eq 0 ] && [ -f "vendor/bin/phpunit" ]; then
echo "Running PHPUnit tests..."
if ! vendor/bin/phpunit --no-coverage; then
echo "Tests failed"
ERROR=1
fi
fi
if [ $ERROR -ne 0 ]; then
echo "Commit rejected due to errors"
exit 1
fi
echo "All checks passed!"
exit 0
2 Commit-msg 钩子(提交信息检查)
文件:.git/hooks/commit-msg
#!/bin/bash
# 检查提交信息格式
MSG_FILE="$1"
MSG=$(cat "$MSG_FILE")
# 获取提交类型
COMMIT_TYPE=$(echo "$MSG" | sed -n '1p' | awk -F'[::]' '{print $1}')
# 支持的提交类型
VALID_TYPES="feat|fix|docs|style|refactor|test|chore|perf|ci|build"
if ! echo "$COMMIT_TYPE" | grep -qE "^($VALID_TYPES)$"; then
echo "Error: Invalid commit type '$COMMIT_TYPE'"
echo "Valid types are: $VALID_TYPES"
echo "Example: feat: add user login functionality"
exit 1
fi
if [ ${#MSG} -lt 10 ]; then
echo "Error: Commit message too short, at least 10 characters needed"
exit 1
fi
3 Post-merge 钩子(合并后检查)
文件:.git/hooks/post-merge
#!/bin/bash
echo "Running post-merge operations..."
# 检查 composer.json 是否变化
if git diff HEAD~1 --name-only | grep -q "composer.json"; then
echo "composer.json changed, installing dependencies..."
composer install --no-dev --optimize-autoloader
fi
# 检查数据库迁移文件
if git diff HEAD~1 --name-only | grep -q "database/migrations"; then
echo "Running database migrations..."
php artisan migrate --force 2>/dev/null || echo "Migration failed or no artisan found"
fi
# 清理缓存(如果是 Laravel)
if [ -f "artisan" ]; then
php artisan cache:clear
php artisan config:clear
fi
echo "Post-merge operations completed!"
4 Pre-push 钩子(推送前检查)
文件:.git/hooks/pre-push
#!/bin/bash
echo "Running pre-push validations..."
# 运行完整测试套件
if [ -f "vendor/bin/phpunit" ]; then
echo "Running full test suite..."
if ! vendor/bin/phpunit; then
echo "Tests failed, push aborted"
exit 1
fi
fi
# 检查 PHP 静态分析
if [ -f "vendor/bin/phpstan" ]; then
echo "Running PHPStan static analysis..."
if ! vendor/bin/phpstan analyse --no-progress; then
echo "PHPStan found issues"
exit 1
fi
fi
echo "All checks passed, ready to push!"
配置文件权限
# 设置执行权限 chmod +x .git/hooks/pre-commit chmod +x .git/hooks/commit-msg chmod +x .git/hooks/post-merge chmod +x .git/hooks/pre-push
配置项目级钩子管理
创建 tools/git-hooks/ 目录存放所有钩子:
文件:tools/git-hooks/pre-commit
#!/bin/bash # 获取项目根目录 ROOT_DIR=$(git rev-parse --show-toplevel) # 使用项目配置变量 CONFIG_FILE="$ROOT_DIR/phpunit.xml" STYLE_STANDARD="PSR12" echo "Using style: $STYLE_STANDARD" echo "Config file: $CONFIG_FILE"
安装钩子的脚本:tools/setup-git-hooks.sh
#!/bin/bash
# 项目钩子安装脚本
set -e
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
HOOK_SOURCE="$PROJECT_DIR/tools/git-hooks"
HOOK_TARGET="$PROJECT_DIR/.git/hooks"
echo "Setting up git hooks..."
for hook in pre-commit commit-msg pre-push post-merge; do
if [ -f "$HOOK_SOURCE/$hook" ]; then
cp "$HOOK_SOURCE/$hook" "$HOOK_TARGET/$hook"
chmod +x "$HOOK_TARGET/$hook"
echo "✓ Installed $hook hook"
fi
done
echo "All git hooks installed successfully!"
Laravel 项目特定钩子
文件:.git/hooks/pre-commit(Laravel专属)
#!/bin/bash
ERROR=0
# 检查 PHP 语法
for file in $(git diff --cached --name-only --diff-filter=ACM | grep '\.php$'); do
if [ -f "$file" ]; then
if ! php -l "$file" > /dev/null 2>&1; then
echo "PHP Syntax Error in: $file"
ERROR=1
fi
fi
done
# Laravel Pint 检查(代码风格)
if [ -f "vendor/bin/pint" ]; then
echo "Running Laravel Pint..."
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.php$')
if [ ! -z "$FILES" ]; then
if ! vendor/bin/pint --test $FILES; then
echo "Laravel Pint style violations found"
ERROR=1
fi
fi
fi
# Laravel 特有检查
if [ -f "artisan" ]; then
echo "Checking Laravel routes..."
if ! php artisan route:list --compact 2>/dev/null | grep -q "Route"; then
echo "Warning: No routes found"
fi
echo "Checking for missing classes..."
if ! composer dump-autoload --no-scripts --dry-run 2>/dev/null | grep -q "."; then
echo "Composer autoload issues"
fi
fi
exit $ERROR
跳过钩子(临时)
# 跳过 pre-commit 和 commit-msg 钩子 git commit -m "message" --no-verify # 跳过 pre-push 钩子 git push --no-verify
使用工具管理钩子
使用 husky + php 集成
package.json(如果有 Node)
{
"husky": {
"hooks": {
"pre-commit": "npm run test && ./scripts/php-checks.sh",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
}
使用 pre-commit 框架
文件:.pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: php-lint
name: PHP Lint
entry: php -l
files: \.php$
language: system
- id: php-cs-fixer
name: PHP CS Fixer
entry: vendor/bin/php-cs-fixer fix
files: \.php$
language: system
调试和测试钩子
# 测试语法检查 git commit -m "test" 2>&1 | grep "PHP" # 查看钩子错误日志 tail -f .git/logs/HEAD # 调试钩子 bash -x .git/hooks/pre-commit
这些配置能帮助你的 PHP 项目提高代码质量、减少错误,并确保团队成员遵循统一的规范,根据项目需求,你可以选择适合的钩子和检查内容。