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

17 阅读5分钟

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

一、Git Tag 是什么?

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

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

commit 1419814  ←──  tag: v1.1.0
commit e368e3a  ←──  tag: v1.0.0

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

二、两种 Tag 类型

轻量标签(Lightweight)

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

git tag v1.0.0

附注标签(Annotated) ✅ 推荐

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

git tag -a v1.0.0 -m "首个正式发布版本"

查看区别:

# 轻量标签 — 只显示 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 常用操作速查

创建

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

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

查看

# 列出所有标签
git tag -l

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

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

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

推送到远程

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

# 推送单个标签
git push origin v1.1.0

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

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

删除

# 删除本地标签
git tag -d v0.6.0

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

基于 Tag 检出代码

# 查看某个版本的代码(进入 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

实际判断技巧

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

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

// 同事的代码
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 自动触发构建和发布

工作流配置

# .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

完整发布流程

# 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 包。

触发条件解析

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 怎么办?

# 删除本地错误 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 只推送分支,不推送标签。必须额外执行:

git push origin v1.1.0
# 或推送所有标签
git push origin --tags

Q3:Tag 和 Branch 有什么区别?

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

Q4:什么时候该打 tag?

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

七、总结

开发完成  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,就构成了一套完整的版本管理与自动发布体系。掌握这套流程,你的项目发布就从"手动打包上传"进化到了"一行命令自动搞定"。


参考资料