vendor目录是只读缓存,所有手动修改会在composer install/update时被覆盖;持久化修改必须通过path仓库或fork+vcs方式实现,而非直接编辑vendor文件。

vendor目录是只读缓存,不是工作区
Composer 把 vendor/ 当作纯输出目录,所有文件都由它控制生命周期。你手动改了 vendor/some/package/src/Helper.php,下次 composer install 或 composer update 时,它会按 composer.lock 里的哈希值校验、解压、覆盖——你的修改没被记录,自然就丢了。
常见错误现象:git status 在 vendor/ 下完全没反应;改完功能正常,一跑 composer update 就退回原版;CI 构建失败,因为别人机器上没你那几行 patch。
- 别在
vendor里git commit——它通常不是完整 Git 仓库(尤其 Packagist 包) - 别依赖“我本地改了就行”——协作、部署、CI 全会翻车
想保留修改,必须让 Composer “认出”你的改动
真正能落地的方式只有两种:用 path 类型仓库,或 repositories + require 切换版本。
path 是最轻量的方案:把想改的包复制到项目外目录(比如 ./packages/my-fix),然后在根 composer.json 里加:
"repositories": [
{
"type": "path",
"url": "./packages/my-fix"
}
],
"require": {
"vendor/package": "dev-main"
}
Composer 会软链接过去,改源码立刻生效,且不会被 composer update 覆盖。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 使用场景:调试第三方包逻辑、快速验证补丁、还没想好要不要提 PR 的临时修改
- 注意:
url是相对路径,CI 构建机必须能访问该路径,否则报source does not exist -
composer.lock会记录这个path条目,但下次composer update可能把它替换成 Packagist 版本,悄无声息回退
长期修改必须走 Fork + VCS 仓库
如果你发现总要改某个包的逻辑,说明它要么设计不够扩展、要么确实有缺陷。这时应该:
- 先看包是否提供事件、hook、macro、service provider 或 contract 接口——比如 Laravel 的
Validator::extend(),优先走这些官方扩展点 - 如果必须改核心逻辑,Fork 该包到自己 GitHub/GitLab,打上语义化标签(如
v1.2.3-myfix),然后在composer.json里用"vcs"仓库引用你的 Fork - 同步给上游提 PR,避免长期维护分支
别用 dev-main 这类开发分支别名“热修复”——它指向远程最新 commit,不是你本地改的代码,composer install 不会拉你本地 patch。
强制重装 ≠ 保留修改,只是刷新状态
composer install --force-reinstall 会强制按 composer.lock 重装所有包:删除 → 下载 → 解压 → 覆盖 → 重建 autoload → 重跑 post-install-cmd。但它依然不认你的手动修改,只会还原锁文件定义的状态。
- 适用场景:
vendor/autoload.php权限错乱、Windows 下 symlink 断裂、某些 bin 文件被手动改坏 - 它不删
vendor/、不动composer.lock,但也不会跳过你改过的文件——照样覆盖 - Windows 下容易因文件被 PhpStorm/Xdebug 占用而失败,建议关掉 IDE 和调试服务后再执行
真正的修改持久化,从来不在 vendor/ 里发生,而在 composer.json 的依赖声明、repositories 配置或上游代码本身里。忽略这点,所有“临时改一下”的操作,最终都会变成线上事故的伏笔。










