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.04. 语义化版本(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. 实际发版流程
一个典型的"发版"操作链:
- 确认 main 上是要发布的代码,跑通所有测试。
git tag -a v1.2.0 -m "feat: 添加用户头像、修复购物车 bug"打附注标签。git push origin v1.2.0推到远程。- 在 GitHub 网页"Releases"里基于这个 tag 写发布说明(自动从 commit 生成)。
- 触发 CI/CD 构建并部署。
GitHub 的 Releases 页面就是基于 tag 的——每个 tag 都能附上 release notes、二进制附件(安装包),用户一眼看到"这个项目发了哪些版本"。
6. 常见误区
- 标签必须推到远程:本地打了不推,等于没打(同事看不到、CI 拿不到)。
- 别重复打同名标签:换版本号就行,不要用
v1.0又指这个又指那个。 - 标签一旦发布就不要改:有人可能已经基于
v1.0.0部署了,你删了重打会让人困惑。发错了就发v1.0.1修正。 - main 分支的每次提交都要能追溯:养成"发版必打 tag"的习惯,以后
git checkout v1.0.0就能精确复现那个版本。
← 上一篇 Git stash 暂存
下一篇 Git 历史与差异 →