必须备份composer.json和composer.lock,因前者声明依赖意图,后者记录精确版本、commit hash、dist shasum及完整依赖树,缺一不可保证发布状态可重现;仅备份vendor不可靠,因其为构建产物,易被修改或不一致。

生产发布前不备份 composer.json 和 composer.lock,等于没锁版本。 你改了代码、升级了依赖、甚至只是重装了 vendor,只要没存下这两份文件,就无法在故障时还原到发布那一刻的精确依赖状态。
为什么必须备份 composer.json + composer.lock 而不是只备份 vendor
vendor 是构建产物,不是源事实。它可能被本地修改、忽略 git、或因权限/缓存问题不一致;而 composer.json 声明意图(要什么),composer.lock 记录结果(实际装了什么)。生产回滚时,你靠的是 lock 文件里每个包的 exact commit hash 或 version + dist shasum,不是靠某次 rsync 过去的 vendor 目录。
-
composer.lock包含所有间接依赖的精确版本、下载 URL、校验和(dist.shasum),缺失它就无法保证“相同命令重装得到相同结果” - 若只备份
composer.json,升级后新装的包可能拉到不兼容的次版本(如"monolog/monolog": "^2.0"在不同时间点可能装 2.10.0 或 2.11.0) - 某些私有仓库配置(如
repositories中的path或自定义 VCS 地址)只存在于composer.json,不备份就丢失上下文
备份位置与命名必须带环境+时间戳
不能把 composer.lock 直接扔进 backup/ 目录然后覆盖——你永远不知道哪次是 prod 发布用的。必须强制带上环境标识和精确时间。
- 推荐路径:
releases/prod-20261102-2215-composer.lock(格式:环境-YYYYMMDD-HHMM-文件名) - 必须同时备份
composer.json,命名对应,如:releases/prod-20261102-2215-composer.json - 禁止使用模糊名称:
latest.lock、prod-backup.json、before-deploy.lock—— 这些在 CI 日志里根本无法追溯 - 备份动作应集成进发布脚本,而非人工执行;例如在
deploy.sh里加一行:cp composer.{json,lock} releases/prod-$(date +%Y%m%d-%H%M)-composer.{json,lock}
CI/CD 流程中必须验证 lock 文件完整性
很多团队在 CI 里跑 composer install 却不校验 lock 是否被意外修改,导致“本地能过,CI 报错”或“上线后行为突变”。
- CI 启动时第一件事:运行
composer validate --no-check-all,检查composer.json格式与字段合法性 - 紧接着运行
composer install --dry-run,确认当前composer.lock能完整解析所有依赖,无缺失或冲突 - 严禁在 CI 中执行
composer update或composer require—— 这会静默改写composer.lock,破坏发布一致性 - 若发现
composer.lock被修改(git diff 有变更),CI 必须失败并报错:LOCK FILE MODIFIED: run 'composer install' locally and commit the updated lock
回滚时直接用备份的 lock 文件重装
线上出问题,别想着“把 vendor tar.gz 解压回去”。正确姿势是切到备份时刻的代码分支 + 替换回对应时间戳的 composer.lock,再跑一次 composer install --no-dev --optimize-autoloader。
- 确保部署机上没有残留的
vendor/目录,或先rm -rf vendor再装,避免 autoload 映射污染 - 如果原
composer.json里用了path类型仓库(如本地开发包),回滚时需确认该路径仍可访问,否则composer install会失败 - 特别注意虚拟包(
replace/provide):它们的声明只在composer.json里,lock 文件不记录实现细节;若回滚到旧版但composer.json没同步,会导致依赖图谱错乱
最常被跳过的一步:备份时没检查 composer.json 里的 repositories 是否包含临时调试配置(比如指向自己 fork 的 private repo),上线后这些地址不可达,composer install 就卡死。每次备份前,先肉眼扫一眼 repositories 和 config 段——这事没法自动化,但漏了就是生产事故。


















