搜索 K
主题
git tag 是 Git 中用于为特定提交打上永久标记的命令。标签通常用于标记发布版本(如 v1.0.0、v2.3.1),是版本管理和发布流程的核心工具。
tag 就像给提交贴一个「书签」——分支会不断前进,但标签永远指向同一个提交,方便你随时回溯到某个确定的版本。
git tag # 列出标签
git tag <tagname> # 创建轻量标签
git tag -a <tagname> -m "message" # 创建附注标签
git tag -d <tagname> # 删除本地标签
git push origin <tagname> # 推送标签到远程
git push origin --tags # 推送所有标签| 类型 | 创建方式 | 存储方式 | 包含信息 | 适用场景 |
|---|---|---|---|---|
| 轻量标签 | git tag <name> | 只是一个指向提交的引用 | 无额外信息 | 临时标记、本地使用 |
| 附注标签 | git tag -a <name> | 独立的 Git 对象 | 标签者、日期、信息、可签名 | 正式发布、团队协作 |
附注标签包含创建者信息、创建日期和标签说明,是正式发布版本的最佳选择。轻量标签适合个人临时标记。
| 对比项 | 标签(Tag) | 分支(Branch) |
|---|---|---|
| 移动性 | 不移动(永远指向同一提交) | 随提交前进 |
| 用途 | 标记版本快照 | 开发线 |
| 推送 | 需要显式推送 | git push 即可 |
| 删除 | 需要显式删除本地和远程 | git branch -d |
# 为当前 HEAD 创建轻量标签
git tag v1.0.0-beta
# 为指定提交创建
git tag v0.9.0 abc1234# 创建附注标签(打开编辑器写信息)
git tag -a v1.0.0
# 直接指定信息
git tag -a v1.0.0 -m "Release v1.0.0: 首个正式版本"
# 为历史提交打标签
git tag -a v0.9.0 abc1234 -m "Release v0.9.0: beta 版本"
# 多行标签信息
git tag -a v2.0.0 -m "Release v2.0.0
主要变更:
- 全新的支付模块
- 性能优化 50%
- 修复 23 个 bug
Breaking Changes:
- API v1 已弃用,请迁移到 v2"# 创建 GPG 签名的标签(用于验证发布者身份)
git tag -s v1.0.0 -m "Signed release v1.0.0"
# 验证签名
git tag -v v1.0.0签名标签通过 GPG 密钥证明「这个版本确实是授权发布者创建的」,常用于:
# 列出所有标签
git tag
# 按模式过滤
git tag -l "v1.*" # v1.x 版本
git tag -l "v2.0.*" # v2.0.x 版本
# 按版本号排序(语义化排序)
git tag -l --sort=version:refname
git tag -l --sort=-version:refname # 倒序
# 查看标签详情
git show v1.0.0
# 附注标签:显示标签信息 + 对应的提交
# 轻量标签:只显示对应的提交
# 查看标签指向的提交
git rev-parse v1.0.0
# 查看所有标签及其指向的提交
git tag -l --format='%(refname:short) → %(objectname:short) %(subject)'# 推送单个标签
git push origin v1.0.0
# 推送所有本地标签
git push origin --tags
# 只推送附注标签(不推送轻量标签)
git push origin --follow-tags
# 配置默认推送附注标签
git config --global push.followTags truegit push 自动推送与分支不同,标签需要显式推送。推荐在 .gitconfig 中设置 push.followTags = true,这样 git push 会自动推送附注标签。
# 删除本地标签
git tag -d v1.0.0-beta
# 删除远程标签
git push origin --delete v1.0.0-beta
# 或
git push origin :refs/tags/v1.0.0-beta
# 批量删除本地标签
git tag -l "v0.*" | xargs git tag -d
# 批量删除远程标签
git tag -l "v0.*" | xargs -I {} git push origin --delete {}Git 标签默认不可修改。如果需要修改,要先删除再重建:
# 移动标签到不同的提交
git tag -d v1.0.0 # 删除本地
git push origin --delete v1.0.0 # 删除远程
git tag -a v1.0.0 <new-commit> -m "Release v1.0.0" # 重建
git push origin v1.0.0 # 推送
# 强制覆盖本地标签(不推荐)
git tag -f v1.0.0 <new-commit>
git push --force origin v1.0.0其他人可能已经基于原始标签进行了工作。移动标签会导致混乱。如果发布有误,更好的做法是:
v1.0.1)v<MAJOR>.<MINOR>.<PATCH>[-<prerelease>][+<buildmetadata>]| 变更类型 | 递增位置 | 示例 |
|---|---|---|
| Bug 修复 | PATCH | 1.0.0 → 1.0.1 |
| 新功能(向后兼容) | MINOR | 1.0.1 → 1.1.0 |
| 破坏性变更 | MAJOR | 1.1.0 → 2.0.0 |
| 预发布版本 | prerelease | 2.0.0-alpha.1 |
| 候选发布版本 | prerelease | 2.0.0-rc.1 |
v2.0.0-alpha.1 # 内部测试版
v2.0.0-alpha.2
v2.0.0-beta.1 # 公开测试版
v2.0.0-beta.2
v2.0.0-rc.1 # 候选发布版(Release Candidate)
v2.0.0-rc.2
v2.0.0 # 正式版# 1. 确保 main 分支是最新的
git checkout main
git pull origin main
# 2. 确认要发布的版本(查看上次发布以来的修改)
git log $(git describe --tags --abbrev=0)..HEAD --oneline
# 3. 更新版本号和 CHANGELOG
vim package.json # 更新 version 字段
vim CHANGELOG.md # 更新变更日志
git add .
git commit -m "chore: bump version to v2.0.0"
# 4. 创建标签
git tag -a v2.0.0 -m "Release v2.0.0
Features:
- 全新支付模块 (#123)
- 用户权限系统 (#456)
Bug Fixes:
- 修复登录超时 (#789)"
# 5. 推送代码和标签
git push origin main --follow-tags大多数 CI/CD 系统支持在创建标签时自动触发发布:
# GitHub Actions 示例
name: Release
on:
push:
tags:
- 'v*' # 匹配 v 开头的标签
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true# 推送标签 → 自动触发构建和发布
git tag -a v2.0.0 -m "Release v2.0.0"
git push origin v2.0.0
# CI/CD 自动:构建 → 测试 → 发布到 npm/Docker/etc# 1. 从出问题的版本创建 hotfix 分支
git checkout -b hotfix/v2.0.1 v2.0.0
# 2. 修复 bug
git commit -m "fix: 修复支付金额计算错误"
# 3. 合并到 main
git checkout main
git merge --no-ff hotfix/v2.0.1
# 4. 创建补丁版本标签
git tag -a v2.0.1 -m "Hotfix v2.0.1: 修复支付金额计算错误"
# 5. 推送
git push origin main --follow-tags
# 6. 清理
git branch -d hotfix/v2.0.1# Alpha 阶段
git tag -a v3.0.0-alpha.1 -m "v3.0.0 Alpha 1: 初始功能集"
# 内部测试...发现问题修复后
git tag -a v3.0.0-alpha.2 -m "v3.0.0 Alpha 2: 修复初始问题"
# Beta 阶段
git tag -a v3.0.0-beta.1 -m "v3.0.0 Beta 1: 功能冻结,开始公测"
# 公测反馈修复后
git tag -a v3.0.0-beta.2 -m "v3.0.0 Beta 2: 修复公测反馈"
# RC 阶段
git tag -a v3.0.0-rc.1 -m "v3.0.0 RC1: 候选发布版"
# 最终确认
git tag -a v3.0.0 -m "v3.0.0: 正式发布"git describe 自动生成版本信息 # git describe 基于最近的标签生成版本描述
git describe --tags
# v2.0.0-15-gabc1234
# 含义:距离 v2.0.0 有 15 个提交,当前 SHA 是 abc1234
# 用于构建版本号
VERSION=$(git describe --tags --always)
echo "当前版本: $VERSION"
# 在代码中注入版本信息
echo "export const VERSION = '$VERSION';" > src/version.ts
# 常用于 CI/CD 构建
docker build -t myapp:$VERSION .# 查看所有发布版本
git tag -l "v*" --sort=-version:refname
# 检出特定版本(detached HEAD)
git checkout v1.5.0
# 基于旧版本创建修复分支
git checkout -b hotfix/from-v1.5 v1.5.0
# 对比两个版本的差异
git diff v1.5.0 v2.0.0 --stat
git log v1.5.0..v2.0.0 --oneline# monorepo 中为不同项目使用不同的标签前缀
git tag -a api/v2.0.0 -m "API v2.0.0"
git tag -a web/v3.1.0 -m "Web v3.1.0"
git tag -a sdk/v1.5.0 -m "SDK v1.5.0"
# 查看特定项目的标签
git tag -l "api/*"
git tag -l "web/*"
# 推送特定项目的标签
git push origin api/v2.0.0git describe 计算版本距离 # 距离最近标签的提交数
git describe --tags --abbrev=0 # 只显示标签名
# v2.0.0
git describe --tags # 完整描述
# v2.0.0-3-gabc1234
# 3 = 距离 v2.0.0 有 3 个新提交
# 只匹配特定模式的标签
git describe --tags --match="v2.*"
# 在脚本中使用
if git describe --tags --exact-match HEAD 2>/dev/null; then
echo "当前 HEAD 有标签,执行发布流程"
else
echo "当前 HEAD 没有标签,跳过发布"
fi# 列出远程标签
git ls-remote --tags origin
# 检查特定标签是否存在于远程
git ls-remote --tags origin | grep "v2.0.0"
# 获取远程标签(不自动获取)
git fetch origin --tags# GitHub:基于标签创建 Release
# 1. 推送标签
git push origin v2.0.0
# 2. 在 GitHub 上从标签创建 Release(可附加二进制文件)
# 或使用 GitHub CLI
gh release create v2.0.0 --generate-notes
# 3. 附加构建产物
gh release upload v2.0.0 dist/app.zip dist/app.dmg
# GitLab:基于标签触发 Release
# .gitlab-ci.yml 中配置
# release:
# tag_name: $CI_COMMIT_TAG
# description: ./CHANGELOG.md# 获取最新标签
LATEST=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "当前版本: $LATEST"
# 解析版本号
MAJOR=$(echo $LATEST | cut -d. -f1 | tr -d v)
MINOR=$(echo $LATEST | cut -d. -f2)
PATCH=$(echo $LATEST | cut -d. -f3)
# 递增 PATCH
NEW_VERSION="v$MAJOR.$MINOR.$((PATCH + 1))"
echo "新版本: $NEW_VERSION"
# 创建新标签
git tag -a $NEW_VERSION -m "Release $NEW_VERSION"# ✅ 推荐的标签命名
v1.0.0 # 语义化版本号
v1.0.0-alpha.1 # 预发布版本
v1.0.0-rc.1 # 候选发布
api/v2.0.0 # monorepo 中的项目前缀
# ❌ 不推荐的标签命名
release-20260308 # 基于日期(不符合 SemVer)
latest # 语义模糊
stable # 不够具体
1.0.0 # 缺少 v 前缀(约定俗成用 v)[alias]
# 列出标签(按版本号排序)
tags = tag -l --sort=-version:refname
# 查看最新标签
latest = describe --tags --abbrev=0
# 查看距最新标签的距离
ver = describe --tags
# 创建附注标签
release = "!f() { git tag -a v$1 -m \"Release v$1\"; }; f"
# 推送标签
push-tags = push origin --follow-tags
# 查看两个标签间的提交
between = "!f() { git log $1..$2 --oneline --no-merges; }; f"
# 使用
git tags # 列出所有标签
git latest # 最新标签
git release 2.0.0 # 创建 v2.0.0
git push-tags # 推送
git between v1.0.0 v2.0.0 # 两个版本间的提交# Node.js 项目:npm version 自动处理版本号 + 标签
npm version patch # 1.0.0 → 1.0.1,自动创建 v1.0.1 标签
npm version minor # 1.0.1 → 1.1.0
npm version major # 1.1.0 → 2.0.0
# npm version 做了什么:
# 1. 更新 package.json 的 version 字段
# 2. git add package.json
# 3. git commit -m "v1.0.1"
# 4. git tag v1.0.1
# Rust 项目
cargo release patch# 同步远程标签到本地(删除本地多余的)
git fetch origin --prune --prune-tags
# 或手动清理
# 1. 查看本地有但远程没有的标签
git tag -l | while read tag; do
git ls-remote --tags origin | grep -q "$tag" || echo "本地多余: $tag"
done
# 2. 删除本地多余的标签
git tag -l "v0.0.*" | xargs git tag -d使用 semantic-release 等工具,根据 Conventional Commits 自动决定版本号并打标签:
# 安装
npm install -D semantic-release
# 工作原理:
# 1. 分析 commit messages
# 2. feat: → MINOR bump
# 3. fix: → PATCH bump
# 4. BREAKING CHANGE: → MAJOR bump
# 5. 自动创建标签 + GitHub Release + CHANGELOG
# .releaserc.json 配置
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/git",
"@semantic-release/github"
]
}不同环境使用不同的标签前缀标记部署版本:
# 标签策略
# v*.*.* — 正式发布版本
# staging-* — staging 部署版本
# canary-* — 金丝雀部署版本
# 部署到 staging
git tag staging-$(date +%Y%m%d-%H%M) HEAD
git push origin staging-$(date +%Y%m%d-%H%M)
# 部署到 canary(灰度发布)
git tag canary-$(git rev-parse --short HEAD) HEAD
git push origin canary-$(git rev-parse --short HEAD)
# 正式发布
git tag -a v3.0.0 -m "Release v3.0.0"
git push origin v3.0.0
# 清理旧的环境标签(保留最近 10 个)
git tag -l "staging-*" | sort | head -n -10 | xargs git tag -d
git tag -l "staging-*" | sort | head -n -10 | xargs -I {} git push origin --delete {}# 两个版本同时部署,标签标记对应版本
git tag -a v3.0.0-variant-a -m "A/B 测试变体 A:新支付流程"
git tag -a v3.0.0-variant-b -m "A/B 测试变体 B:旧支付流程"
# CI/CD 根据标签部署到不同的服务实例
# variant-a → 50% 流量
# variant-b → 50% 流量
# A/B 测试结束后,胜出的变体成为正式版本
git tag -a v3.0.0 -m "Release v3.0.0: 采用变体 A 的支付流程"# 生产环境出问题,需要快速回退到上一个版本
# 1. 查看最近的版本标签
git tag -l "v*" --sort=-version:refname | head -5
# v3.0.0 ← 当前有问题的版本
# v2.9.0
# v2.8.1
# v2.8.0
# 2. 确认回退目标
git log v2.9.0..v3.0.0 --oneline # 查看这之间改了什么
# 3. 方式一:部署旧标签
# CI/CD 重新部署 v2.9.0 标签(不修改代码)
# 4. 方式二:从旧标签创建 hotfix
git checkout -b hotfix/rollback v2.9.0
# 可能需要 cherry-pick 一些 v3.0.0 中的关键修复
git cherry-pick <safe-fixes-from-v3>
git tag -a v2.9.1 -m "Hotfix v2.9.1: 从 v3.0.0 回退"
git push origin v2.9.1# 构建时用 Git 标签作为 Docker 镜像版本
VERSION=$(git describe --tags --always)
docker build -t myapp:$VERSION .
docker tag myapp:$VERSION registry.example.com/myapp:$VERSION
docker push registry.example.com/myapp:$VERSION
# 正式版本额外标记 latest
if git describe --tags --exact-match HEAD 2>/dev/null | grep -q "^v[0-9]"; then
docker tag myapp:$VERSION registry.example.com/myapp:latest
docker push registry.example.com/myapp:latest
fi
# Kubernetes 部署时引用标签版本
# deployment.yaml
# image: registry.example.com/myapp:v3.0.0#!/bin/bash
# bump-version.sh — 交互式版本号递增工具
LATEST=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "当前版本: $LATEST"
echo ""
MAJOR=$(echo $LATEST | sed 's/v//' | cut -d. -f1)
MINOR=$(echo $LATEST | sed 's/v//' | cut -d. -f2)
PATCH=$(echo $LATEST | sed 's/v//' | cut -d. -f3 | cut -d- -f1)
echo "选择版本类型:"
echo " 1) patch → v$MAJOR.$MINOR.$((PATCH + 1))"
echo " 2) minor → v$MAJOR.$((MINOR + 1)).0"
echo " 3) major → v$((MAJOR + 1)).0.0"
echo " 4) 自定义"
read -p "选择 [1-4]: " choice
case $choice in
1) NEW="v$MAJOR.$MINOR.$((PATCH + 1))" ;;
2) NEW="v$MAJOR.$((MINOR + 1)).0" ;;
3) NEW="v$((MAJOR + 1)).0.0" ;;
4) read -p "输入版本号 (如 v3.0.0-beta.1): " NEW ;;
esac
echo ""
echo "即将创建标签: $NEW"
echo "变更日志 ($LATEST..$NEW):"
git log $LATEST..HEAD --oneline --no-merges
echo ""
read -p "确认? [y/N]: " confirm
if [ "$confirm" = "y" ]; then
git tag -a $NEW -m "Release $NEW"
echo "✅ 标签 $NEW 已创建"
read -p "推送到远程? [y/N]: " push
if [ "$push" = "y" ]; then
git push origin $NEW
echo "✅ 已推送"
fi
fi# ❌ 创建了标签但忘记推送
git tag -a v2.0.0 -m "Release v2.0.0"
git push origin main
# 标签没有被推送!CI/CD 不会触发发布
# ✅ 推送代码时一起推送标签
git push origin main --follow-tags
# 或配置默认行为
git config --global push.followTags true# ❌ 轻量标签没有创建者信息
git tag v1.0.0
git show v1.0.0
# 只显示提交信息,不显示谁创建了标签
# ✅ 使用附注标签
git tag -a v1.0.0 -m "Release v1.0.0"
git show v1.0.0
# 显示标签创建者、日期和信息# ❌ 标签和分支同名会导致歧义
git tag release
git branch release
# 引用时需要显式指定
git checkout tags/release # 检出标签
git checkout refs/heads/release # 检出分支
# ✅ 使用 v 前缀避免冲突
git tag v1.0.0 # 标签
git branch release/v1.0 # 分支# ❌ 移动已推送的标签
git tag -f v2.0.0 <new-sha>
git push --force origin v2.0.0
# 其他人的 v2.0.0 还指向旧提交!需要所有人重新 fetch
# ✅ 创建新的补丁版本
git tag -a v2.0.1 -m "v2.0.1: 修复 v2.0.0 中的问题"# 检出标签会进入 detached HEAD
git checkout v1.0.0
# 你正处于 'detached HEAD' 状态
# ❌ 在这里提交会丢失
git commit -m "fix something"
git checkout main # 提交变成悬空对象!
# ✅ 从标签创建分支再提交
git checkout -b hotfix/from-v1.0.0 v1.0.0
git commit -m "fix something"git tag -d v1.0.0
git tag -a v1.0.0 -m "正确的标签信息"git push origin --delete v1.0.0
git tag -d v1.0.0
git tag -a v1.0.0 <correct-sha> -m "正确的标签信息"
git push origin v1.0.0v1.0.1)# 提交列表
git log v1.0.0..v2.0.0 --oneline --no-merges
# 代码差异
git diff v1.0.0 v2.0.0 --stat
# 详细 diff
git diff v1.0.0 v2.0.0git fetch 会自动获取标签吗?默认情况下,git fetch 会获取你已有分支所指向的标签,但不会获取所有标签。要获取所有标签:
git fetch --tags
git fetch origin --prune --prune-tags # 同步并清理git checkout -b hotfix/from-v1.0 v1.0.0
# 或
git switch -c hotfix/from-v1.0 v1.0.0不能直接转换。需要删除轻量标签,重新创建附注标签:
# 记录轻量标签指向的提交
SHA=$(git rev-parse v1.0.0)
# 删除轻量标签
git tag -d v1.0.0
# 创建附注标签
git tag -a v1.0.0 $SHA -m "Release v1.0.0"# 创建多行标签信息
git tag -a v2.0.0 -m "Release v2.0.0`n`n- Feature A`n- Feature B"
# 或使用编辑器
git tag -a v2.0.0 # 打开默认编辑器| 目标 | 命令 |
|---|---|
| 列出所有标签 | git tag |
| 按模式过滤 | git tag -l "v2.*" |
| 按版本排序 | git tag -l --sort=-version:refname |
| 创建轻量标签 | git tag <name> |
| 创建附注标签 | git tag -a <name> -m "message" |
| 为历史提交打标签 | git tag -a <name> <sha> -m "message" |
| 创建签名标签 | git tag -s <name> -m "message" |
| 查看标签详情 | git show <tagname> |
| 删除本地标签 | git tag -d <tagname> |
| 删除远程标签 | git push origin --delete <tagname> |
| 推送单个标签 | git push origin <tagname> |
| 推送所有标签 | git push origin --tags |
| 推送附注标签 | git push origin --follow-tags |
| 获取远程标签 | git fetch --tags |
| 检出标签 | git checkout <tagname> |
| 从标签创建分支 | git checkout -b <branch> <tagname> |
| 最新标签 | git describe --tags --abbrev=0 |
| 当前版本描述 | git describe --tags |
| 两标签间的提交 | git log <tag1>..<tag2> --oneline |
| 强制覆盖标签 | git tag -f <name> <sha> |
| 同步远程标签 | git fetch origin --prune --prune-tags |
git describe — 基于标签生成版本描述git archive — 基于标签导出代码归档