PHP 怎么配置Git钩子

wen PHP项目 2

本文目录导读:

PHP 怎么配置Git钩子

  1. Git 钩子基础
  2. 常用 PHP 项目钩子配置
  3. 配置文件权限
  4. 配置项目级钩子管理
  5. Laravel 项目特定钩子
  6. 跳过钩子(临时)
  7. 使用工具管理钩子
  8. 调试和测试钩子

我来详细介绍如何配置 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 项目提高代码质量、减少错误,并确保团队成员遵循统一的规范,根据项目需求,你可以选择适合的钩子和检查内容。

抱歉,评论功能暂时关闭!