Git tag 标签 — 版本号管理

分支是指向"会变动的提交"的指针,而 tag(标签)是指向某个固定提交的"不动书签"。它最经典的用途是标记发布版本:每次发版给那个提交打个 v1.0.0 的标签,以后随时能精确回到"那个时刻的项目状态"。这一章讲怎么打标签、两种标签的区别、以及语义化版本号规范。

1. 给提交打标签

# 给当前提交打标签(标记"这是一个发布版本")
git tag v1.0.0                  # 轻量标签(只是个指针)
git tag -a v1.0.0 -m "正式版 1.0" # 附注标签(推荐,带信息)

# 给历史某个提交补打标签
git tag -a v0.9.0 a1b2c3d -m "事后标记的 0.9 测试版"

# 查看所有标签
git tag
# v0.9.0
# v1.0.0
# v1.1.0

# 按模式筛选
git tag -l "v1.*"
# v1.0.0
# v1.1.0

# 看某个标签的详情(附注标签才有信息)
git show v1.0.0
# tag v1.0.0
# Tagger: 你的名字 <you@example.com>
# Date:   Mon Aug 5 10:00:00 2025
#
# 正式版 1.0
#
# commit e4f5g6h (tag: v1.0.0)
# ...

标签和分支的关键区别:分支会随提交前移,标签永远指向同一个提交。所以"v1.0.0"这个标签,无论你之后怎么开发,永远代表"打标签那一刻的项目快照"——这正是发布版本需要的"不可变"特性。

2. 轻量标签 vs 附注标签

Git 有两种标签,理解区别很重要:

# 轻量标签(lightweight)vs 附注标签(annotated)
#
# 轻量标签:只是一个指向提交的指针(像个书签)
git tag v1.0.0
#
# 附注标签:一个完整的 Git 对象,包含:
#   - 标签名
#   - 打标签的人(名字+邮箱)
#   - 打标签的日期
#   - 标签信息(message)
#   - 指向的提交
git tag -a v1.0.0 -m "正式版 1.0"

# 官方推荐用附注标签(annotated),因为:
#   - 信息完整(谁、何时、为什么打的)
#   - 可以被 GPG 签名(防伪造)
#   - 适合"发布版本"这种正式场合
#
# 轻量标签适合"临时标记一下,给自己看的"

# 给附注标签签名(GPG,高级用法,确保来源可信)
git tag -s v1.0.0 -m "签名版 1.0"
# 验证签名
git tag -v v1.0.0

官方强烈推荐用附注标签(-a)做正式发布——它记录了"谁、何时、为什么"打这个标签,日后排查问题、生成 release notes 都靠这些信息。轻量标签更像"临时记号",适合个人使用。

3. 推送与删除标签

一个大坑:标签默认不会随 git push 一起推到远程!必须显式推送。很多人本地打了 tag,以为远程也有,结果同事 clone 下来什么标签都没有。

# 标签默认不会随 git push 推到远程!要显式推送
git push origin v1.0.0          # 推一个标签
git push origin --tags          # 推送所有本地标签

# 推送时同时带标签(--follow-tags)
git push --follow-tags

# 删除标签
git tag -d v1.0.0               # 删本地标签
git push origin --delete v1.0.0 # 删远程标签

# 检出某个标签对应的版本(进入 detached HEAD)
git checkout v1.0.0
# 或
git switch --detach v1.0.0

# 想在 v1.0.0 基础上修 bug,建分支
git switch -c hotfix/v1.0.1 v1.0.0

4. 语义化版本(SemVer)

版本号不是随便起的,业界有语义化版本(Semantic Versioning)规范,让版本号本身就传达"这次升级改了什么、兼容性如何":

# 语义化版本(SemVer):MAJOR.MINOR.PATCH
#   v1.4.2
#    ↑ ↑ ↑
#    | | └── PATCH:向后兼容的 bug 修复(1.4.2 → 1.4.3)
#    | └──── MINOR:向后兼容的新功能(1.4.2 → 1.5.0)
#    └────── MAJOR:不兼容的重大改动(1.4.2 → 2.0.0)
#
# 规则:
#   - 修复 bug 但不影响 API:升 PATCH
#   - 加新功能、旧 API 还能用:升 MINOR
#   - 改了 API 导致旧代码不能用:升 MAJOR
#
# 预发布版本(还没正式发):
#   v2.0.0-alpha.1    内部测试
#   v2.0.0-beta.1     公开测试
#   v2.0.0-rc.1       发布候选(Release Candidate)

# 用 git describe 看当前离最近的标签有多远
git describe
# 输出: v1.4.2-3-ga1b2c3d
# 含义:距离 v1.4.2 有 3 个提交,当前提交哈希 a1b2c3d
# 适合自动化构建版本号

SemVer 是现代软件包管理(npm、cargo、pip)的基石——依赖管理工具靠版本号判断"能不能自动升级"。严格遵守 SemVer,你的用户才能放心地 npm update

5. 实际发版流程

一个典型的"发版"操作链:

GitHub 的 Releases 页面就是基于 tag 的——每个 tag 都能附上 release notes、二进制附件(安装包),用户一眼看到"这个项目发了哪些版本"。

6. 常见误区

← 上一篇 Git stash 暂存

下一篇 Git 历史与差异

✈️💬