composer本身不生成或读取git tag来设版本,仅消费composer.json中静态version字段;自动版本需在ci构建时用git describe生成语义化版本并注入环境变量或version文件,而非修改composer.json。

Composer 本身不生成版本号,也不读取 Git Tag 来自动设版本——它只消费 version 字段。想让项目在持续交付中“自动带 Git Tag 版本”,关键不在 Composer 配置,而在构建时动态注入。
Composer 的 version 字段是静态的,不是运行时变量
很多人误以为在 composer.json 里写 "version": "dev-main" 或留空就能自动更新,其实:version 字段仅用于包发布(packagist.org)或本地安装时的约束解析;Composer 安装时完全忽略它是否匹配当前 Git 状态。
- 如果
version字段存在且是稳定格式(如"1.2.3"),Packagist 会把它当作正式版收录 - 如果写成
"dev-main"或"@dev",Packagist 不收录为稳定版,且本地composer install不校验 Git commit 是否匹配 - CI 构建时即使 Git 已打 tag,
composer.json里的version不变 → 最终部署包仍显示旧值
用 git describe 在构建时生成语义化版本并注入
真正起作用的是 CI 脚本(如 GitHub Actions、GitLab CI),在打包前调用 git describe 获取最近 tag,并写入可被应用读取的位置——不是改 composer.json,而是生成一个运行时可用的版本文件。
适用于以下场景:(1)用户提供 GitHub 仓库 URL 或本地仓库路径,并请求将其转换为其他格式;(2)用户请求导出 GitHub 仓库……
- 推荐命令:
git describe --tags --abbrev=6 --dirty=-dev,输出类似v2.1.0-3-gabc123-dirty(表示距 v2.1.0 有 3 个提交,哈希前 6 位,加 -dirty 表示工作区有修改) - 不要直接覆盖
composer.json:会污染 git 状态,且 Composer lock 文件可能因字段变更被误重算 - 更安全做法:生成
VERSION文件或注入环境变量APP_VERSION,PHP 应用启动时读取该值 - 示例(GitHub Actions):
echo "APP_VERSION=$(git describe --tags --abbrev=6 --dirty=-dev 2>/dev/null || echo 'dev-unknown')" >> $GITHUB_ENV
PHP 应用如何可靠读取构建时版本?
硬编码或从 composer.json 解析都不可靠;应优先信任构建环境注入的标识。
- 读环境变量最轻量:
$_SERVER['APP_VERSION'] ?? 'dev-snapshot' - 若需持久化(如 CLI 命令输出版本),可构建时写入
src/Version.php:echo "<?php return '" . escapeshellarg($VERSION) . ";" > src/Version.php
- 避免用
exec('git describe...')运行时调用:容器镜像通常不含 Git,且有性能与权限风险 - 注意:Laravel 的
Artisan::version()默认读composer.json,需重写逻辑才能对接构建版本
Git Tag 是事实来源,Composer 只是元数据载体。自动版本的核心动作永远发生在 CI 构建阶段——生成、注入、验证。任何试图让 Composer “自己感知 tag” 的方案,都会绕过构建可控性,最终在灰度发布或回滚时暴露问题。










