不能。Composer 本身不提供 Git 状态检测能力,composer run-script 仅执行 scripts 字段定义的命令,需手动添加 git status --porcelain 等命令实现未提交代码检查。

composer run-script 能不能直接检查未提交代码?
不能。Composer 本身不提供 Git 状态检测能力,composer run-script 只负责执行你定义在 scripts 字段里的命令,它不会自动读取 Git 工作区状态。所谓“检查未提交代码”,本质是调用 git status --porcelain 或类似命令,必须你自己写进脚本里。
怎么在 composer.json 中定义一个「检查未提交」的脚本?
在 composer.json 的 scripts 段添加一条 shell 命令即可,关键是用 git status --porcelain 判断是否有修改:
"scripts": {
"check:dirty": "git status --porcelain | grep -q '.' || (echo '✅ No uncommitted changes.' && exit 0) || (echo '❌ Uncommitted changes detected.' && exit 1)"
}说明与要点:
-
git status --porcelain输出为空表示干净;有任意输出(哪怕只有一行)就代表存在未提交变更 -
grep -q '.'是最简判断:只要匹配到任意字符即视为“有输出”,避免空格/换行干扰 - 该命令退出码为 1 时,CI 或
composer run-script会中止后续流程,适合用在 pre-commit 或 CI 的前置检查中 - Windows 用户注意:
git必须在 PATH 中,且 PowerShell/CMD 对管道语法支持有限,建议在 Git Bash 或 WSL 下运行 - 如果只想检查特定目录(如只关心
src/),加-- src/参数:git status --porcelain -- src/
为什么加了脚本但运行没反应或总成功?
常见失效原因不是逻辑错,而是环境或配置问题:
-
scripts字段拼写错误:必须是"scripts"(全小写、无空格、无冒号后空格),写成"script"或"Scripts"都无效 - 脚本名含非法字符:比如用了中文、全角标点、或开头数字,会导致 Composer 忽略该条目
- Git 不在 PATH:某些 CI 环境(如最小化 Alpine 镜像)默认没装 Git,
git: command not found会被静默吞掉,脚本退出码为 127,但 Composer 默认不报错——加--verbose可看到真实错误 - 项目不在 Git 仓库根目录:脚本执行时当前工作目录是项目根(含
composer.json),但如果该目录下没有.git,git status会失败 - 使用了
composer run-script check:dirty --no-ansi等参数干扰输出,但不影响退出码逻辑
和 pre-commit hook 配合时要注意什么?
很多团队想把「检查未提交」塞进 pre-commit,但这里有个关键陷阱:
- pre-commit hook 运行时,Git 尚未暂存新文件,
git status --porcelain会显示?? newfile.php——这属于「未跟踪文件」,是否算“脏”取决于你的定义 - 如果你只关心已跟踪但未提交的修改(
M、D、MM等),应改用:git status --porcelain --ignored=no | grep '^[MADRC]' - 不要在 hook 里直接调用
composer run-script,因为 hook 执行路径可能不是项目根;推荐写成独立 shell 脚本并硬编码项目路径,或确保cd $(git rev-parse --show-toplevel)先切过去 - IDE 自动保存 + Git 插件(如 PHPStorm 的 Commit dialog)有时会绕过 hook,实际提交前仍需人工确认
真正要靠住的,不是脚本有没有运行,而是它的退出码是否被下游流程(CI、hook、Makefile)严格消费。别信输出文字,盯住 $?。


















