HOWTO · Git

在 Git 中移动现有标签

将现有 Git 标签移动到指定提交,并在需要时更新远程标签。

本页内容

Git 标签用于标记仓库历史中的特定位置,通常是一个提交。你可以将本地标签移动到指定提交;如果团队同意,也可以替换远程引用。更改他人用于发布的标签前,请先与协作者沟通:他们可能已经获取了旧目标,自动构建或发布记录也可能依赖该目标。

了解 Git 标签及移动标签的风险

轻量标签是对 Git 对象的直接引用,通常指向一个提交。带注释的标签则是包含消息和标签者元数据的独立 Git 对象,也可以带有签名。替换标签会改变该名称解析到的对象。重新创建带注释的标签时,必须再次提供消息;重新创建签名标签时,也必须重新签名。新的标签对象不会保留旧对象或旧签名。

更改标签前,先用 git show --no-patch --format=%H <tag> 确认它当前指向哪里,再决定要将它改为指向哪个提交。请为新目标指定提交 ID 或其他明确的版本,不要依赖当前检出的提交。如果标签由多人共用,请告知协作者预期的新目标,并提醒他们可能需要刷新本地副本。

将本地标签移动到另一个提交

使用 git tag -f <tag> <commit> 可直接移动本地标签。-f 选项会替换现有的本地标签。对于带注释的标签,可用 git tag -f -a <tag> <commit> -m "<message>" 重新创建注释;如果标签必须签名,则用 -s 替代 -a,并按仓库要求配置签名。适当时,请保留原有消息及其发布含义。

请在已安装 Git 的 shell 中运行此示例。示例代码块保持与英文原文逐字一致,因此其中显示的标签状态文字仍为英文。

set -eu
repo_dir=$(mktemp -d)
trap 'rm -rf "$repo_dir"' EXIT
git -C "$repo_dir" init -q
git -C "$repo_dir" config user.name "Example User"
git -C "$repo_dir" config user.email "example@example.com"
printf 'first\n' > "$repo_dir/file.txt"
git -C "$repo_dir" add file.txt
git -C "$repo_dir" commit -qm "first commit"
first_commit=$(git -C "$repo_dir" rev-parse HEAD)
git -C "$repo_dir" tag v1.0 "$first_commit"
printf 'second\n' >> "$repo_dir/file.txt"
git -C "$repo_dir" commit -qam "second commit"
target_commit=$(git -C "$repo_dir" rev-parse HEAD)
git -C "$repo_dir" tag -f v1.0 "$target_commit" >/dev/null
tag_commit=$(git -C "$repo_dir" rev-parse refs/tags/v1.0)
if [ "$tag_commit" = "$target_commit" ]; then
  printf 'tag points to intended commit: yes\n'
else
  printf 'tag points to intended commit: no\n'
fi

在自己的仓库中,将实际标签名称和目标提交替换到命令中。如果普通命令 git tag <tag> <commit> 提示标签已存在,这是预期行为:只有确认替换目标无误后,才使用强制选项。

更新远程标签

与协作者沟通后,使用 git push --force origin <tag> 只更新指定的远程标签。这会替换该标签的远程引用,但仍在使用旧目标的协作者仍可能受到影响。如果只打算更改一个标签,请勿推送所有标签。如果服务器拒绝更新,请检查仓库权限和服务器端的标签保护规则,不要反复尝试强制推送。

获取他人更新的标签

如果其他人移动了远程标签,你的本地标签可能仍指向旧目标。使用 git fetch origin tag <tag> 获取指定标签。如果 Git 提示获取操作会覆盖现有本地标签,请用 git tag -d <tag> 删除本地引用,然后再次获取指定标签。删除本地引用不会删除远程标签。这种错误不同于获取成功但引用保持不变的情况;一般的 git pull 不能可靠地代替显式获取这个标签。

验证标签是否指向预期提交

使用 git rev-parse <tag>^{} 检查本地标签对应的提交。后缀 ^{} 会剥离带注释的标签,得到它最终指向的提交。将完整提交 ID 与预期提交进行比较,例如与 git rev-parse <commit> 返回的 ID 比较。

若要检查远程标签而不更改本地引用,请运行 git ls-remote --tags origin <tag>。这种写法会匹配指定标签及其剥离后的引用。对于带注释的标签,以 ^{} 结尾的那一行给出了标签最终指向的提交;请将该提交 ID 与预期提交进行比较。协作者更改共用标签后,请告知大家新的目标,以便所有人确认自己使用的是同一个发布引用。