在 composer.json 中添加 pre-commit 钩子需借助 brainmaestro/composer-git-hooks:dev 依赖该包,scripts 中定义 "pre-commit" 命令,通过 "post-install-cmd" 和 "post-update-cmd" 调用 cghooks install 自动生成 .git/hooks/pre-commit 文件。

composer.json 里怎么加 pre-commit 钩子
Composer 本身不执行 Git hooks,pre-commit 是 Git 的钩子,必须靠第三方工具或手动集成。最直接的做法是用 composer install 或 composer update 触发钩子安装,但前提是项目里已引入支持钩子的包(比如 brainmaestro/composer-git-hooks)。
实操建议:
- 在
composer.json的"require-dev"中添加"brainmaestro/composer-git-hooks": "^2.8" - 在
"scripts"下定义钩子命令,例如:"pre-commit": "php-cs-fixer fix --dry-run --using-cache=no" - 加一个
"post-install-cmd"和"post-update-cmd"脚本,调用vendor/bin/cghooks install(这是composer-git-hooks提供的命令) - 确保
.git/hooks/pre-commit文件被生成且可执行;如果没生成,手动运行一次vendor/bin/cghooks install
为什么 pre-commit 脚本不运行
常见现象:改完代码 git commit,什么都没发生,也没报错 —— 实际上钩子根本没触发。原因通常是:.git/hooks/pre-commit 文件不存在、不可执行,或内容被覆盖。
排查要点:
- 检查
.git/hooks/pre-commit是否存在,权限是否为755(Linux/macOS)或对应可执行状态(Windows 需.bat或.ps1) - 确认该文件内容不是空的,也不是原始 Git 模板(含
exit 1或注释开头的默认内容) - 如果用了
husky或其他 Node 工具管理 hooks,它会覆盖 Composer 工具生成的脚本 —— 二者不能混用 -
composer-git-hooks默认只在post-install-cmd和post-update-cmd时写入钩子,首次克隆仓库后没运行composer install就不会生效
pre-commit 里跑 php-cs-fixer 或 phpstan 报错路径不对
典型错误信息:Could not open input file: vendor/bin/php-cs-fixer 或 PHP Fatal error: Uncaught Error: Class 'PhpCsFixer\Finder' not found。
本质是钩子脚本执行时工作目录不是项目根目录,或未加载 Composer 自动加载器。
解决办法:
- 所有命令都用相对路径调用,例如
./vendor/bin/php-cs-fixer(注意前面的./) - 避免在
pre-commit脚本里用cd切换目录,Git hooks 默认在 Git 工作区根目录执行,但某些环境(如 Windows Git Bash)可能 cwd 不稳定 - 若用
phpstan,加--configuration=phpstan.neon显式指定配置路径,避免因相对路径解析失败找不到配置 - 不推荐在钩子里直接
require vendor/autoload.php写 PHP 脚本 —— 可维护性差,也容易出 autoloader 冲突
CI 环境下 pre-commit 被跳过,但本地又想强制校验
Git hooks 天然只在本地生效,CI(如 GitHub Actions)完全不走 .git/hooks/。所以别指望 CI 会自动跑你的 pre-commit 脚本。
正确做法是把校验逻辑复用到 CI 流程中:
- 把
pre-commit里实际执行的命令(如./vendor/bin/php-cs-fixer fix --dry-run)单独抽成一个composer script,比如"check-style" - CI 的 job 步骤里显式运行
composer run check-style - 本地开发时,仍靠
pre-commit钩子自动触发;CI 则靠明确命令保证一致性 - 注意:不要在
pre-commit里做耗时操作(如全量phpstan analyse),它会拖慢每次提交;CI 才适合跑完整扫描
钩子真正起作用的地方,是开发者日常小步提交时的即时反馈。一旦依赖它做复杂检查,反而容易被绕过或误关 —— 这点比技术实现更关键。










