Git Tag + Semver + CI/CD:从打标签到自动发布的完整实践

本文从一个真实的前端项目出发,梳理 Git Tag 的核心用法、语义化版本规范,以及如何配合 GitHub Actions 实现"打 tag 即发布"的自动化流程。

一、Git Tag 是什么?

你可以把 Tag 理解为 Git 仓库的版本书签

每次 git commit 产生的 hash(如 1419814)对人类不友好,而 Tag 让你给某个 commit 取一个有意义的名字:

sql 复制代码
commit 1419814  ←──  tag: v1.1.0
commit e368e3a  ←──  tag: v1.0.0

与分支(branch)不同,Tag 一旦创建就不会随新提交移动,永远指向那个固定的 commit。这使它非常适合标记发布版本。

二、两种 Tag 类型

轻量标签(Lightweight)

只是 commit 的别名,不包含额外信息:

bash 复制代码
git tag v1.0.0

附注标签(Annotated) ✅ 推荐

包含作者、日期、说明信息,是一个完整的 Git 对象:

bash 复制代码
git tag -a v1.0.0 -m "首个正式发布版本"

查看区别:

bash 复制代码
# 轻量标签 --- 只显示 commit 信息
git show v1.0.0

# 附注标签 --- 额外显示 tag 作者、日期、说明
git show v1.1.0
# Tagger: Rayner <xxx@xxx.com>
# Date:   Sun Mar 2 11:34:00 2026 +0800
# feat(diagnosis): add autocomplete presets...

实践建议:正式版本一律用附注标签,轻量标签留给临时标记或个人备忘。

三、Tag 常用操作速查

创建

bash 复制代码
# 给当前 HEAD 打标签
git tag -a v1.1.0 -m "feat: 新增初诊预设自动匹配功能"

# 给历史 commit 补打标签
git tag -a v0.9.0 abc1234 -m "beta 版本"

查看

bash 复制代码
# 列出所有标签
git tag -l

# 按版本号降序排列(推荐)
git tag -l --sort=-v:refname

# 模糊筛选
git tag -l "v1.*"

# 查看标签详情
git show v1.1.0

推送到远程

重点git push 默认不推送标签!必须显式推送:

bash 复制代码
# 推送单个标签
git push origin v1.1.0

# 推送所有本地标签
git push origin --tags

这是新手最常踩的坑 --- 本地打了标签以为万事大吉,结果远程仓库和 CI/CD 完全无感知。

删除

bash 复制代码
# 删除本地标签
git tag -d v0.6.0

# 删除远程标签
git push origin --delete v0.6.0

基于 Tag 检出代码

bash 复制代码
# 查看某个版本的代码(进入 detached HEAD 状态)
git checkout v1.0.0

# 基于某个 tag 创建新分支进行修复
git checkout -b hotfix/v1.0.1 v1.0.0

四、语义化版本(Semantic Versioning)

Tag 命名推荐遵循 Semver 2.0.0 规范,格式为 vMAJOR.MINOR.PATCH

复制代码
v1.1.0
 │ │ │
 │ │ └── PATCH 修订号:向下兼容的 bug 修复
 │ └──── MINOR 次版本号:向下兼容的新功能
 └────── MAJOR 主版本号:包含破坏性变更

版本递增规则

变更类型 举例 版本变化
修复 bug 修复登录页白屏 v1.0.0v1.0.1
新增功能(向下兼容) 新增初诊预设短语 v1.0.0v1.1.0
破坏性变更 API 接口重构、移除旧功能 v1.1.0v2.0.0

实际判断技巧

核心问题:升级版本后,原来能跑的代码会不会炸?

举个具体例子,假设你维护一个诊断模块,别的同事在调用你的函数:

ts 复制代码
// 同事的代码
import { updateDiagnosis } from '@/services/diagnosis';
updateDiagnosis(patientId, diagnosisId, { chief_complaint: '头晕' });

三种情况:

你做的变更 同事的代码需要改吗? 版本 原因
修复了 updateDiagnosis 内部的一个空指针 bug 不需要,升级即修复 patch 行为修正,接口没变
新增了 PresetTextArea 组件 不需要,原来的代码照常用 minor 新功能是增量的,不影响已有代码
updateDiagnosis(patientId, id, data) 改成了 updateDiagnosis({ patientId, id, ...data }) 需要! 调用方的参数格式得全改 major 接口签名变了,原来的调用会报错

简单口诀:

  • 升级后原来的代码炸了 → major
  • 升级后原来的代码没炸,但多了新东西可以用 → minor
  • 升级后原来的代码没炸,只是 bug 少了 → patch

Ant Design 的版本实践

Ant Design 遵循同样的 Semver 规范,它的发布节奏是:

  • patch:每周末日常 bugfix
  • minor:每月发布带有新特性的向下兼容版本
  • major:包含破坏性更新,不在固定周期内(如 antd v5 → v6)

五、Tag + GitHub Actions = 自动发布

这是 Tag 最实用的场景:推送 tag 自动触发构建和发布

工作流配置

yaml 复制代码
# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*.*.*'   # 匹配所有 semver 格式的 tag

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - run: npm ci
      - run: npm run build

      # 打包构建产物
      - name: Package dist
        run: zip -r dist-${{ github.ref_name }}.zip dist/

      # 创建 GitHub Release 并上传附件
      - name: Create Release
        uses: softprops/action-gh-release@v2
        with:
          generate_release_notes: true
          files: dist-${{ github.ref_name }}.zip

完整发布流程

bash 复制代码
# 1. 开发完成,提交代码
git add .
git commit -m "feat(diagnosis): add autocomplete presets"

# 2. 推送代码
git push

# 3. 打附注标签
git tag -a v1.1.0 -m "feat: 新增初诊预设自动匹配功能"

# 4. 推送标签(触发 CI/CD)
git push origin v1.1.0

# 5. GitHub Actions 自动执行:
#    checkout → install → build → zip → create release

推送 tag 后,在 GitHub 仓库的 Actions 页面可以看到 workflow 被触发,完成后会在 Releases 页面生成一个新版本,附带构建产物的 zip 包。

触发条件解析

yaml 复制代码
on:
  push:
    tags:
      - 'v*.*.*'
  • v1.0.0 --- 匹配 ✅
  • v1.1.0 --- 匹配 ✅
  • v2.0.0-beta.1 --- 不匹配 ❌(多了 -beta.1
  • release-1.0 --- 不匹配 ❌(缺少 v 前缀)

如果需要匹配预发布版本,可以改为 'v*' 或添加 'v*.*.*-*'

六、常见问题

Q1:打错了 tag 怎么办?

bash 复制代码
# 删除本地错误 tag
git tag -d v0.6.0

# 如果已推送到远程,也要删除远程
git push origin --delete v0.6.0

# 重新打正确的 tag
git tag -a v1.1.0 -m "正确的版本"
git push origin v1.1.0

Q2:忘记推送 tag,CI/CD 没触发?

git push 只推送分支,不推送标签。必须额外执行:

bash 复制代码
git push origin v1.1.0
# 或推送所有标签
git push origin --tags

Q3:Tag 和 Branch 有什么区别?

特性 Tag Branch
是否移动 固定不动 随 commit 前移
用途 标记版本快照 开发分支
推送方式 需显式推送 git push 自动推送

Q4:什么时候该打 tag?

  • 功能开发完成、测试通过、准备发布时
  • 不要在开发过程中频繁打 tag
  • 一个 tag 对应一个可发布的稳定版本

七、总结

yaml 复制代码
开发完成 → git commit → git tag -a vX.Y.Z → git push origin vX.Y.Z
                                  │
                          遵循 Semver 规范
                          patch: 修 bug
                          minor: 加功能
                          major: 破坏性更新
                                  │
                          推送触发 CI/CD → 自动构建发布

Git Tag 本身很简单,但结合语义化版本和 CI/CD,就构成了一套完整的版本管理与自动发布体系。掌握这套流程,你的项目发布就从"手动打包上传"进化到了"一行命令自动搞定"。


参考资料

相关推荐
徐小夕3 小时前
JitWord Office预览引擎:如何用Vue3+Node.js打造丝滑的PDF/Excel/PPT嵌入方案
前端·vue.js·github
程序员鱼皮3 小时前
离大谱,我竟然在 VS Code 里做了个视频!
github·aigc·ai编程
答案answer6 小时前
一个非常实用的Three.js3D模型爆破💥和切割开源插件
前端·github·three.js
草梅友仁7 小时前
墨梅博客 1.7.0 发布与 AI 开发实践 | 2026 年第 9 周草梅周报
开源·github·ai编程
ursazoo1 天前
写了一份 7000字指南,让 AI 帮我消化每天的信息流
人工智能·开源·github
小兵张健1 天前
Playwright MCP 截图标注方案调研(推荐方案1)
前端·javascript·github