version 字段非必需,但若填写必须符合 SemVer 2.0 规范且与 Git 状态一致;本地开发中硬写 version 会导致安装失败;私有包通过 path 引入时 version 被忽略;仅在发布分发包或 CI/CD 动态生成构建号时建议显式设置;日常开发应删除 version,依赖 Git 标签和 branch-alias 管理版本。

version 字段不是必须填的,但填了就得符合规范
Composer 不强制要求 composer.json 中定义 version 字段。如果你没写,Composer 会根据 Git 标签(如 v1.2.3)或分支名(如 dev-main)自动推断版本。但一旦你手动写了 "version": "1.2.3",就必须满足 SemVer 2.0 规范,且不能和 Git 状态冲突——否则 composer install 可能报错:Root package cannot be installed because it is not available in the configured repositories。
- 只允许使用
1.2.3、1.2.3-beta.1、1.2.3+build.456这类标准格式,1.2或1.2.3.4都不合法 - 如果项目是本地开发态(无 Git 标签),又硬写了
"version": "1.0.0",Composer 会拒绝安装依赖,除非加--ignore-platform-reqs(不推荐) - 私有包若通过
path仓库引入,其version字段会被完全忽略,实际版本以父项目的require中指定的约束为准
什么时候该显式写 version?常见于发布包场景
只有两类情况建议显式设置 version:
- 打包为可分发的私有包(比如放在 Satis 或 Private Packagist 上),且希望明确锁定某次构建的语义化版本
- CI/CD 流水线中生成带构建号的版本(如
2.1.0+git.abc123),此时需配合脚本动态写入composer.json,再执行composer install --no-interaction
注意:GitHub/GitLab 仓库直接作为 Composer 包使用时,version 字段会被 Git 标签覆盖,手动写的值不起作用。
version 和 package name 共同决定包的唯一标识
Composer 把 {"name": "vendor/name", "version": "1.2.3"} 当作一个完整包坐标。这意味着:
- 同一
name下,不同version值会被视为不同包(即使代码完全一样) - 如果你在
require中写"vendor/name": "^1.2",而该包的composer.json里version是"1.2.0-dev",那它不会被匹配——因为-dev后缀属于不稳定版本,默认不启用 - 运行
composer show vendor/name输出的版本号,优先显示 Git 标签,其次才是version字段值
想动态控制版本号?别碰 version 字段,改用 branch-alias 或 version constraint
日常开发中,硬编码 version 很容易导致协作混乱。更稳妥的做法是:
- 删掉
version字段,靠 Git 标签管理发布版本 - 在
extra中配branch-alias,例如:{ "extra": { "branch-alias": { "dev-main": "2.3.x-dev" } } }这样其他项目require "vendor/name": "^2.3"就能命中main分支 - 发布前用
git tag v2.3.0 && git push origin v2.3.0,比手改version更可靠
真正容易被忽略的是:哪怕你只改了 version 字段,也相当于修改了包的身份标识,所有依赖它的项目都可能因版本解析失败而中断构建。










