应删除冲突的composer.lock和vendor目录,再以合并后的composer.json为准运行composer update --lock或composer install重建锁文件;切勿手动编辑lock文件,因其是依赖图哈希快照而非配置文件。

composer.lock Git 合并冲突时别手动改
直接编辑 composer.lock 文件解决冲突是高危操作——它不是配置文件,而是依赖图的哈希快照。改错一个 content-hash 字段或某包的 dist.reference,下次 composer install 就会报 Package foo/bar is not installed 或静默跳过加载。
Git 报冲突,本质是两个分支各自执行过 composer update、composer require 或 PHP 版本约束变更,导致依赖树结构、版本号、校验值不一致。这不是“内容要合并”,而是“快照需重建”。
- 先运行
git status,确认只有composer.lock冲突,composer.json必须无冲突——否则得先理清依赖声明差异 - 用
composer show --outdated看当前 lock 是否已过时(比如主干已升 Laravel 11,你分支还锁在 v10) - 若双方改动仅限新增/删除同类型包(如都加了
monolog/monolog),可直接弃用当前分支的 lock,checkout 主干 lock 后运行composer install
冲突后最稳重建流程:删 lock + 重装
当两边都有实质性依赖变更(比如分支 A 升了 guzzlehttp/guzzle,分支 B 加了 spatie/laravel-backup),手动挑行没意义,应以 composer.json 为准重建整个依赖状态。
- 先确保
composer.json已正确合并(含require、require-dev、config、platform全部字段) - 删掉本地
composer.lock和vendor/目录(不要只删 lock) - 运行
composer update --lock:它不改依赖版本,只按当前composer.json和现有vendor/重新生成一致哈希和 dist 引用 - 若 vendor 已删干净,就直接
composer install——前提是 CI/CD 环境信任 lock 文件
CI/CD 构建失败常因 .gitattributes 没配
很多团队构建失败不是 Composer 的问题,而是 Git 默认把 composer.lock 当普通文本合并,产出非法 JSON。错误现象包括:构建时 file_get_contents(composer.lock): failed to open stream,或解析出 Parse error: syntax error, unexpected '{'。
- 在项目根目录加
.gitattributes文件,写入一行:composer.lock merge=ours(主干优先)或composer.lock merge=theirs(功能分支优先) - 这个设置让 Git 在冲突时跳过自动合并,直接采用指定版本,避免生成损坏 JSON
- 配完后推送到远端,所有新 clone 或 pull 都会生效;旧仓库需
git config merge.ours.driver true注册驱动
为什么不能用 composer-merge-plugin
composer-merge-plugin 早已停止维护,且设计逻辑反模式:它试图“合并”多个 composer.lock,但 lock 文件不是配置项,无法像 YAML 那样做字段级合并。官方明确不支持多源 lock 合并。
真正该做的是流程控制:
- 开发中避免在 feature 分支跑
composer update,只用composer require/composer remove——这些命令自动更新 lock,变更集中、语义清晰 - 合入前,在 feature 分支上执行
composer update --lock,同步哈希值再提交,让 lock 变更更干净 - 关键依赖升级(如框架大版本)必须单独 PR,附带
composer show --tree截图,而不是混在业务代码里
require-dev 包全程参与依赖解析。哪怕你只跑 composer install --no-dev,phpunit/phpunit 对 sebastian/exporter 的版本锁定,仍会封死 symfony/console 的升级路径。查冲突时,composer why-not 输出为空?第一反应该去 require-dev 里翻。


















