composer.lock冲突不能直接“保留双方”,因其是精确依赖快照,手动合并易致损坏;正确做法是用composer install重新生成权威锁文件,并遵循三条协作规则确保一致性。

为什么 composer.lock 冲突不能直接“保留双方”
因为 composer.lock 是精确依赖快照,不是声明式配置。Git 合并时若两个分支各自运行过 composer install 或 composer update,composer.lock 中的 content-hash、包版本、哈希值、安装路径等字段极大概率不一致,手动合并极易导致锁文件损坏——下次 composer install 会报 Content hash mismatch 或安装出错。
标准流程:用 composer install 覆盖冲突,而非手动编辑
当 Pull Request 或本地 merge 出现 composer.lock 冲突时,正确做法是放弃冲突标记,让 Composer 重新生成一份权威锁文件:
- 先 checkout 到目标分支(如
main),运行git checkout --ours composer.lock或git checkout --theirs composer.lock任选其一暂存(仅用于解除冲突状态) - 立刻执行
composer install --no-dev(或带--dev,需与项目实际环境一致) - Composer 会根据当前
composer.json重新计算依赖树、校验哈希、生成全新composer.lock -
git add composer.lock提交新锁文件
这保证了锁文件与 composer.json 严格一致,且所有开发者获得完全相同的依赖安装结果。
团队协作中必须约定的三条规则
光解决单次冲突不够,得从流程上堵住源头:
-
composer.json修改后,必须立即运行composer update xxx(或composer install)并提交更新后的composer.lock—— 不允许只提composer.json不提锁文件 - CI 流水线必须校验:运行
composer install后执行git status --porcelain composer.lock,若有输出则失败(说明锁文件未同步) - 禁止在 CI 或部署机上运行
composer update;生产环境只允许composer install --no-dev --prefer-dist --optimize-autoloader
特殊情况:需要保留某分支的特定包版本怎么办
比如 A 分支升级了 monolog/monolog 到 3.0.0,B 分支仍用 2.9.1,而你希望最终锁文件锁定 2.9.1。这时不能靠 Git 选 ours/theirs,而应:
- 先完成 merge(解决其他文件冲突),确保
composer.json中"monolog/monolog": "^2.9"存在 - 运行
composer require monolog/monolog:^2.9 --no-update(仅改 json) - 再运行
composer update monolog/monolog --with-all-dependencies(强制重算该包及其传递依赖) - 检查
composer.lock中对应条目是否为2.9.1,再提交
直接改 composer.lock 手动降级版本号是危险操作,Composer 不会验证 integrity,后续 install 可能失败。
composer install --no-dev git status --porcelain composer.lock
真正容易被忽略的点是:很多人以为 composer.lock 只是“缓存”,其实它是可重现构建的契约。只要团队里有人跳过 install 直接改 json 就提交,冲突就会反复出现,而且越来越难对齐。










