composer install 必须读 lock 文件,因其本质是“按图索骥,原样还原”,严格依据 lock 中的版本号、commit hash、dist URL 和校验和安装,完全忽略 json 中的版本约束。

composer install 为什么必须读 lock 文件?
因为 composer install 的本质不是“装满足条件的最新版”,而是“按图索骥,原样还原”。它只认 composer.lock 里写的版本号、commit hash、dist URL 和校验和,完全忽略 composer.json 里的 ^2.0 或 ~3.5 这类范围约束。
常见错误现象:
- 本地开发能跑,CI 构建失败,报
Class 'Symfony\Component\HttpClient\HttpClient' not found - 同事执行
composer install后vendor/里guzzlehttp/guzzle是 7.8.1,你的是 7.9.0 —— 但两人都没动过composer.json
原因只有一个:lock 文件没提交,或被误删。此时 composer install 会退化成隐式 composer update,重新解析整个依赖树,结果不可控。
lock 文件冲突了,别手动合并
composer.lock 不是普通配置文件,它是整个依赖图的完整序列化快照,手动删几行、保留“这边的”或“那边的”字段,大概率导致依赖不一致甚至安装失败。
正确做法是放弃冲突解决,靠 Composer 重建:
- 运行
git checkout --ours composer.lock或git checkout --theirs composer.lock(任选其一还原) - 删掉
vendor/目录(确保干净) - 运行
composer install—— 它会基于当前composer.json和刚恢复的 lock 重新校验并生成一份新 lock - 如果提示
Your lock file does not contain a compatible set of packages,说明composer.json已被他人修改过,先git pull拉最新,再composer install
什么时候该用 composer update?
composer update 是主动升级动作,不是日常命令。它会重算整个依赖树,可能引入未经测试的小版本、破坏性变更,甚至降级(比如因 PHP 版本限制跳过新包,回退到带已知 bug 的旧版)。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
使用场景非常明确:
- 要升级某个包到新主版本,如把
laravel/framework从^10.0升到^11.0 - 修复安全扫描工具报出的高危漏洞(如
monolog/monologCVE-2025-1234) - 适配新 PHP 版本(如升到 PHP 8.4,需更新不兼容的扩展依赖)
实操建议:
- 升级单个包时加
--with-all-dependencies,避免主包升级了、子依赖卡在旧版导致行为异常 - CI 脚本里禁止出现
composer update,除非你明确要刷新基线 - 每次
composer update后,必须git add composer.lock并提交
为什么 vendor/ 绝对不能提交进 Git?
vendor/ 是构建产物,不是源码。它体积大(常超百 MB)、含平台相关二进制(如 ext-redis 的 .so 文件)、Git 无法有效 diff,还会拖慢克隆和检出速度。
更关键的是:一旦 vendor/ 被提交,团队成员就可能绕过 composer install 直接用现成的目录,lock 文件形同虚设,环境一致性彻底失控。
务必确认项目根目录有 .gitignore,且包含这一行:/vendor/。漏掉这行,等于默认放弃 Composer 的核心价值。
复杂点在于:有人会说“我们 CI 慢,想缓存 vendor”,那是构建优化问题,不是提交 vendor/ 的理由 —— 正确解法是用 Composer cache、Docker layer 缓存或 CI artifact 复用,而不是污染 Git 历史。

















