composer status 只检测以 --prefer-source 安装且含 .git 目录的包,若包为 dist 模式(无 .git)、私有包漏配 source 或 type、或 .git 被删除,则完全静音;空输出不表示 vendor 干净。

composer status 只能检查出以 --prefer-source 方式安装、且当前 Git 工作区存在未提交变更的包——它不比对文件内容哈希,也不扫描 dist 包,更不关心你改的是不是 PHP 代码。
为什么改了 vendor 里的文件却没输出?
空输出 ≠ vendor 干净。它只扫描带 .git 目录的包,而默认 prefer-dist: true 导致 90% 以上包走 zip 解压,vendor/monolog/monolog 下根本没有 .git,自然跳过。
- 验证方式:
composer show monolog/monolog,若输出中无source字段,说明该包是 dist 模式,status对它完全静音 - 私有包漏配
"type": "package"或没声明"source",即使本地有 Git 仓库也无效 - 手动删过
vendor/xxx/.git,或执行过git clean -fd,也会让status认为“没改”
哪些修改它真能检测到?
仅当包以 source 模式安装、且 Git 能识别出工作区变更时,status 才会标记 modified。典型场景包括:
-
git status --porcelain有输出:如M src/Logger.php(已修改)、?? debug.php(未跟踪新文件) - 当前分支 HEAD 与
composer.lock中记录的 commit hash 不一致(比如你git checkout dev-feature切了分支) - 暂存区有改动(
git add src/Logger.php后未提交)
注意:status 不检测 vendor/autoload.php 或 vendor/composer/ 下的自动生成文件;也不处理 path 类型仓库引入的本地包。
看到 modified 后怎么定位具体改了啥?
composer status -v 只告诉你包名和路径,不显示 diff 内容。真正要看改动,必须进包目录用 Git:
- 先运行:
composer status -v,找到类似monolog/monolog modified (src/Logger.php)的行 - 再执行:
cd vendor/monolog/monolog && git diff HEAD --stat查改动概览,或git diff看完整差异 - 一行脚本批量查所有 modified 包(Linux/macOS):
composer status | grep "modified" | cut -d' ' -f1 | xargs -I{} sh -c 'echo "\n=== {} ==="; cd vendor/{} && git status -s 2>/dev/null'
别依赖 composer status 输出格式写自动化逻辑——加 -v 后字段顺序可能变,只适合人眼扫。
它和真正的完整性校验有本质区别
composer status 是元数据驱动的轻量检查,依赖 composer.lock 记录的原始快照(Git hash 或 dist checksum),不是文件级哈希比对。一旦 lock 被手改、不同步,或包本身没提供 source 地址,结果就不可信。
最稳的方式永远是绕过 Composer,直接进 vendor/xxx 运行 git status --porcelain —— 它不看 lock,只认 Git 工作区状态,且不受 prefer-dist 影响。但前提是:那个目录下真有 .git。











