不能提交vendor目录,因其是根据composer.json和composer.lock动态生成的构建产物,非源码;含平台相关文件、易致冲突膨胀、破坏环境一致性,应仅提交composer.json与composer.lock并用git rm -r --cached vendor清理已跟踪项。

Composer 从不上传 vendor 目录,这是设计使然,不是遗漏或配置错误。
vendor 目录为什么不能提交到 Git
vendor 是依赖求解器(Solver)根据 composer.json 和 composer.lock 动态生成的结果目录,不是源码的一部分。它包含大量第三方代码、自动生成的 autoloader、以及与当前环境强耦合的路径信息。
- 不同系统(Linux/macOS/Windows)下 symlink 行为、文件权限、大小写敏感性可能让 vendor 内容不一致
- 同一份
composer.lock在 PHP 8.1 和 8.3 下,某些包的子依赖可能因config.platform.php差异而解析出不同版本 - 私有包若使用 SSH URL,vendor 里会存有本地 clone 的 git metadata,推送到公共仓库会暴露路径甚至密钥痕迹
- Git diff 体积爆炸:一个中等项目 vendor 轻松超 50MB,每次更新都触发全量 diff,拖慢 clone 和 CI
只提交 composer.lock 才能保证环境一致
composer.lock 是 Solver 输出的「已验证可行解」,它记录了每个包的确切版本、commit hash(对 dev 分支)、安装来源(dist 或 source)和完整依赖树快照。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 团队成员、CI 服务器、生产环境只要运行
composer install(而非update),就一定会装出完全一致的 vendor 结构 - 删掉
composer.lock后执行composer install,等价于运行composer update—— 因为没有锁文件,Solver 只能重新计算最新兼容组合 - 如果
composer.json里写了"monolog/monolog": "^2.0",但 lock 文件里是2.10.0,install 就绝不会装2.11.0,哪怕它已发布
CI/CD 和生产环境必须用 install + --no-dev + --optimize-autoloader
很多线上事故源于没加关键参数,不是版本写错了,而是执行方式不对。
-
composer install读取 lock 文件;composer update忽略 lock、重新求解——生产部署脚本里出现update就是高危操作 - 漏掉
--no-dev会导致phpunit、phpstan等 dev-only 包被装进生产环境,可能意外启用 debugbar 或暴露_profiler路由 -
--optimize-autoloader生成 classmap,跳过 PSR-4 的文件扫描,PHP 请求启动快 20%~40%,尤其在容器冷启动时明显 - Dockerfile 中应写死:
RUN composer install --no-dev --optimize-autoloader --no-interaction,不依赖 .env 或环境变量覆盖
误删 lock 文件后 vendor 不一致,不是 bug 是必然
当 composer.lock 不存在时,Composer 唯一依据只剩 composer.json 里的约束范围。而这个范围往往很宽:
-
"guzzlehttp/guzzle": "^7.0"在 2026 年 5 月可匹配7.9.1或7.8.1,取决于当时 packagist 缓存状态和 Solver 随机种子 - 你本地装的是
7.8.1,队友装的是7.9.0,两者都满足^7.0,但后者可能含一个你不兼容的内部方法签名变更 - 这种差异不会报错,直到某次日志格式变更或 HTTP header 处理逻辑微调才暴露
真正难控的不是版本号本身,而是约束符号(^ / ~)在不同主版本下的语义漂移,以及它如何与整个依赖图联动——一个 ^ 写错,可能让周五下午的 CI 构建突然开始失败。










