composer install 从 packagist 或配置镜像源下载预打包的 dist 归档(.zip/.tar.gz),内容与 lock 文件中记录的 tag 对应 commit 一致;私有 vcs 包例外,按 lock 中 source reference 执行 git clone。

因为 Composer install 不拉远程仓库,它只按 composer.lock 文件还原已锁定的版本 —— 这是设计使然,不是 bug。
composer install 从哪取代码?
它完全不访问远程 Git 仓库(除非你强制用了 --prefer-source),而是从 Packagist 或你配置的镜像源下载预打包的 .zip 或 .tar.gz 归档(即 dist 包)。这些归档由包作者在发布 tag 时生成,内容与该 tag 对应的 Git commit 一致。
也就是说:composer install 的目标是「复现 lock 文件记录的状态」,不是「同步最新 Git 提交」。
- 如果你看到本地装的版本和 GitHub 上
main分支最新提交不一致,正常 —— 因为main没打 tag,Packagist 就不会收录 - 如果你改了
composer.json里某个包的版本约束(比如从"^2.0"改成"dev-main"),composer install不会生效 —— 它只认composer.lock,必须先composer update - 私有 VCS 包(如
"type": "vcs")例外:它会在install时走git clone,但前提是composer.lock里记录的是source类型,且 commit hash 明确
为什么 git clone 出来的 commit 和 lock 文件对不上?
当你用 --prefer-source 强制走 Git 克隆路径时,Composer 会按 composer.lock 中记录的 reference(通常是 commit hash)执行 git checkout。但如果本地 vendor/xxx/.git 目录残留了旧分支或未清理的 dirty 状态,Git 可能 checkout 失败,回退到 HEAD 或当前分支 tip,导致实际代码和 lock 不符。
- 典型现象:
composer install --prefer-source后,git -C vendor/package log -1显示的 commit 和composer.lock里"reference"字段不一致 - 根本原因:vendor 目录下残留的
.git目录被复用,而没做 clean + reset - 解法:删掉
vendor/package整个目录再重装;或加--no-cache避免复用旧克隆 - 注意:
--no-cache不影响composer.lock校验,只控制是否复用已有的source目录
怎么确认装的到底是不是 lock 文件指定的版本?
别信 composer show 输出的版本号 —— 它显示的是包的 version 字段,可能被包作者手动写死,和实际代码无关。唯一权威依据是 composer.lock 里的 "source" 或 "dist" 块。
- 查 dist 包:看
"dist": {"url": "...", "reference": "xxx"}—— 这个reference是归档生成时对应的 commit hash - 查 source 包:看
"source": {"url": "...", "reference": "xxx"}—— 这个reference就是git checkout的目标 - 验证方式:
sha256sum vendor/package/composer/installed.json | cut -d' ' -f1应和 lock 文件中该包的"dist"."shasum"一致(dist 方式) - Git 方式验证:
git -C vendor/package rev-parse HEAD必须等于 lock 里的"source"."reference"
最容易被忽略的一点:lock 文件本身可能已损坏或被手动编辑过。只要 "reference" 字段被改错、或 "shasum" 没同步更新,Composer 就会静默装错包 —— 它只校验 hash,不校验 commit 是否真实存在。











