只更新单个包必须用完整包名加斜杠,如composer update vendor/package-name;漏斜杠报错,加引号可能引发全量更新;连带升级直系依赖需用--with而非已移除的--with-dependencies。

只更新一个包,必须用完整包名加斜杠
想精准控制更新范围,composer update vendor/package-name 是唯一可靠写法。漏掉 /(比如写成 composer update monolog)会报错 Package "monolog" not found;加引号(如 "monolog/monolog")可能被 shell 解析失败,退化为全量更新。
这个命令的行为是确定的:
- 只按
composer.json中该包的版本约束(例如"^2.8")拉取最新兼容版 - 仅顺带升级它**直系依赖**中未被其他顶层包锁死的部分(比如
psr/log若需升到^2.0才能装monolog2.10,就会升) - 完全不动
laravel/framework、guzzlehttp/guzzle等其他顶层包 - 修改只写入
composer.lock中对应包的version、source、dist字段
连带更新直系依赖要用 --with,不是 --with-dependencies
--with-dependencies 在 Composer 2.2+ 已被移除,执行会直接报错:Unrecognized option: --with-dependencies。现在要控制依赖树的升级深度,得用 --with 参数:
-
composer update guzzlehttp/guzzle --with psr/http-message—— 只升指定的直系依赖 -
composer update guzzlehttp/guzzle --with-all-dependencies—— 升整棵依赖树(含子依赖的子依赖) - 多个包用空格分隔:
--with psr/http-message nyholm/psr7,不能用逗号或换行
更新前先看它到底依赖谁
盲目更新容易引发连锁反应。运行 composer show vendor/package-name 能查出它的 require 列表,预判哪些直系依赖可能被连带升级。比如 monolog/monolog:^3.0 明确要求 "symfony/console": "^6.2",而你 composer.lock 里是 6.1,那它就必须升——这种连带升级无法禁掉,是语义化版本 + 依赖求解的必然结果。
确认是否真只动了目标包?加 --dry-run -n 先看输出:composer update monolog/monolog --dry-run -n,输出里如果只含 monolog/monolog 及其直系依赖,就说明没波及其他顶层包。
锁死版本时 update 不生效,得先改约束
如果 composer.json 里写的是 "monolog/monolog": "2.9.0" 这种精确版本,composer update monolog/monolog 不会做任何事——它被锁死了。必须先改成松散约束,比如 "^2.9" 或删掉具体版本号,再执行 update。
另外,composer.lock 文件本身不能手动编辑。遇到合并冲突,优先用 composer update --lock 重建锁文件;若想保留某个分支的依赖状态,应接受其 composer.json 和 composer.lock,再重新执行另一个分支的 composer require 操作。
真正容易被忽略的是:直系依赖的连带升级不可控,但它是求解器基于约束推导出的唯一合法解。你以为只动了一个包,其实背后已经跑了一次 SAT 求解。











