Composer元数据仅包括composer.json、composer.lock和Git提交历史;前者声明依赖规则,后者记录精确版本与源类型,提交历史承载变更依据,三者共同构成可重现的协作契约。

团队协作中 Composer 元数据不能靠“手动复制”备份,必须通过 Git 管理 composer.json 和 composer.lock,其他所谓“配置备份”若脱离这两个文件,基本等于没备。
哪些文件算 Composer 元数据?只认这三个
Composer 的元数据不是指缓存、全局 config 或 vendor,而是项目依赖关系的唯一权威声明。它只由以下三个文件构成:
-
composer.json:声明 require / autoload / scripts / repositories 等逻辑规则 -
composer.lock:记录所有包精确版本、校验和、源类型(vcs/path/composer)、安装路径 —— 这是composer install的执行依据 - (隐含)Git 提交历史:
composer.lock的每次变更必须对应composer.json修改 + 明确的升级理由(如 PR 标题写清 “upgrade monolog to 3.5.0 for CVE-2026-XXXX”)
其他都非元数据:~/.config/composer/config.json 是本地偏好,vendor/ 是产物,cache/ 可丢弃 —— 它们都不参与依赖解析,也不该进 Git。
为什么不能只备份 composer.json?
只提交 composer.json 而忽略 composer.lock,等于把依赖解析权交给每个开发者本地环境。后果包括:
- 不同人运行
composer install装出不同版本的monolog/monolog(比如一个装 2.10,一个装 3.0),但composer.json里只写了"^2.0 || ^3.0" - CI 构建时因网络波动或 packagist 暂不可用,自动 fallback 到旧版或失败
- 某次
composer update后没提交 lock,新成员拉代码直接install,得到的是上周五的依赖快照,而非你测试过的那套
关键点:composer.lock 不是“可选附件”,它是 Composer 协作模型的契约文件 —— 它的存在,就是为了让 install 可重现。
团队共享管理必须禁用的三件事
以下操作看似省事,实则破坏元数据一致性,已在多个团队引发线上事故:
- 禁止在 CI 中执行
composer update后自动生成并提交composer.lock—— 这绕过人工审查,可能引入不兼容变更 - 禁止在
composer.json的repositories里写绝对路径(如"url": "/home/alex/mylib")或环境变量(如"url": "${HOME}/mylib"),这类配置无法被他人复现,composer install直接跳过该仓库 - 禁止在 Git 忽略列表(
.gitignore)里加入composer.lock—— 常见于老项目迁移,结果所有分支的依赖状态彻底失控
真正需要共享的,只是干净的 composer.json + 经测试的 composer.lock + 清晰的 commit message。其余全是干扰项。
私有源配置也属于元数据,必须进 composer.json
如果团队用了 Satis、Private Packagist 或 VCS 私有源,这些信息不是“环境配置”,而是项目依赖图的一部分,必须显式写在 composer.json 的 repositories 字段里:
{
"repositories": [
{ "type": "composer", "url": "https://satis.internal/" },
{ "packagist": false }
]
}
常见错误:
- 用
composer config repositories.xxx写进全局配置 —— 这只影响当前机器,CI 和新成员完全看不到 - 漏掉
{ "packagist": false },导致 Composer 仍偷偷连packagist.org,私有包冲突或覆盖失败 - URL 缺末尾斜杠(如
"https://satis.internal"),请求变成/packages.json而非//packages.json,404 后静默降级到官方源
私有源地址一旦写进 composer.json,就和 require 的包名一样,是项目元数据的刚性组成部分 —— 改动它,就必须走代码评审流程。











