如何将git分支上的标签移动到其他提交?


858

我在master分支上创建了一个标签,v0.1如下所示:

git tag -a v0.1

但是后来我意识到,对于版本0.1,我仍然需要合并到master中进行一些更改,所以我做到了。但是现在我的v0.1标签卡在了错误的提交上(以引用便利贴的类比)。我希望它停留在master的最近一次提交上,但是它停留在master的第二次最近提交上。

如何将其移至对master的最新提交?

Answers:


1198

使用该-f选项可以git tag

-f
--force

    Replace an existing tag with the given name (instead of failing)

您可能想与-f一起使用,-a以强制创建带注释的标签,而不是非带注释的标签。

  1. 按下前删除任何遥控器上的标签

    git push origin :refs/tags/<tagname>
    
  2. 替换标签以引用最新的提交

    git tag -fa <tagname>
    
  3. 将标签推到远端

    git push origin master --tags
    

90
最好在执行任何操作之前,先删除任何遥控器上的标签,方法是:git push origin :refs/tag/<tagname>先执行git tag -fa <tagname>然后再执行git push origin master --tags。否则,您可能会在遥控器的引用列表中添加奇怪的东西,并附加^和{}字符。感谢codebasehq.com上的Dan指出了这一点。
eedeep 2011年

47
@eedeep:较小的更正- :refs/tag/<tagname>应该是:refs/tags/<tagname>
本·霍金

8
仅当您尚未从计算机中推送代码时,此方法才有效。如果有的话,最好的答案是“世界上有很多数字”,因为这不值得麻烦。
克里斯·黄·利弗

33
如果您已经推送了标签,则仍然可以通过强制推git push -f origin <tagname>
送来

11
这里和文档中未提及的是,如果没有给出新消息,这确实会移动标记消息。
Twonky

259

更准确地说,您必须强制添加标签,然后使用--tags和-f选项进行推送:

git tag -f -a <tagname>
git push -f --tags

171

总结一下是否调用了远程origin并且您正在master分支上:

git tag -d <tagname>
git push origin :refs/tags/<tagname>
git tag <tagname> <commitId>
git push origin <tagname>
  • 第1行删除了本地环境中的标签。
  • 第2行删除了远程环境中的标签。
  • 第3行将标签添加到其他提交
  • 第4行将更改推送到远程

您还可以交换第4行,git push origin --tags以使用本地更改中的标记推送所有更改。

基于@ stuart-golodetz,@ greg-hewgill,@ eedeep,@ ben-hocking答案,其答案下方的评论以及我的答案下方的NateS评论。



47

使用Git时,我尽量避免一些事情。

  1. 使用内部知识,例如参考/标签。我尝试仅使用记录在案的Git命令,并避免使用需要了解.git目录内部内容的内容。(也就是说,我将Git视为Git用户,而不是Git开发人员。)

  2. 不需要时使用武力。

  3. 过分的事情。(按一下分支和/或很多标签,在我想要的位置获得一个标签。)

因此,这是我在不了解Git内部知识的情况下在本地和远程更改标签的非暴力解决方案。

当软件修复最终有问题并且需要更新/重新发布时,我会使用它。

git tag -d fix123                # delete the old local tag
git push github :fix123          # delete the old remote tag (use for each affected remote)
git tag fix123 790a621265        # create a new local tag
git push github fix123           # push new tag to remote    (use for each affected remote)

github是一个示例远程名称,fix123是一个示例标记名称,以及790a621265一个示例提交。


26

我将在这里留下另一种适合我需要的命令。我想移动
一个标签v0.0.1.2

$ git tag -f v0.0.1.2 63eff6a

Updated tag 'v0.0.1.2' (was 8078562)

然后:

$ git push --tags --force

好,谢谢,2个平原和简单的命令
塞尔吉奥

10

另一种方式:

在远程仓库中移动标签(如果需要,请用其他标签替换HEAD)。

$ git push --force origin HEAD:refs/tags/v0.0.1.2

取回更改。

$ git fetch --tags

这比其他答案更具“交易性”。
贾斯汀·凯斯

9

将一个标签移动到另一提交的别名。

在您的样品,以招犯了哈希e2ea1639做:git tagm v0.1 e2ea1639

对于推送的标签,请使用git tagmp v0.1 e2ea1639

这两个别名都会使您保留原始日期和消息。如果您使用,git tag -d则会丢失原始消息。

将它们保存在您的.gitconfig文件中

# Return date of tag. (To use in another alias)
tag-date = "!git show $1 | awk '{ if ($1 == \"Date:\") { print substr($0, index($0,$3)) }}' | tail -2 | head -1 #"

# Show tag message
tag-message = "!git show $1 | awk -v capture=0 '{ if(capture) message=message\"\\n\"$0}; BEGIN {message=\"\"}; { if ($1 == \"Date:\" && length(message)==0 ) {capture=1}; if ($1 == \"commit\" ) {capture=0}  }; END { print message }' | sed '$ d' | cat -s #"

### Move tag. Use: git tagm <tagname> <newcommit> 
tagm = "!GIT_TAG_MESSAGE=$(git tag-message $1) && GIT_COMMITTER_DATE=$(git tag-date $1) && git tag-message $1 && git tag -d $1 && git tag -a $1 $2 -m \"$GIT_TAG_MESSAGE\" #"

### Move pushed tag. Use: git tagmp <tagname> <newcommit> 
tagmp = "!git tagm $1 $2 && git push --delete origin $1 && git push origin $1 #"

1

如果要移动带注释的标签,请仅更改目标提交,但保留注释消息和其他元数据,方法是:

moveTag() {
  local tagName=$1
  # Support passing branch/tag names (not just full commit hashes)
  local newTarget=$(git rev-parse $2^{commit})

  git cat-file -p refs/tags/$tagName | 
    sed "1 s/^object .*$/object $newTarget/g" | 
    git hash-object -w --stdin -t tag | 
    xargs -I {} git update-ref refs/tags/$tagName {}
}

用法:moveTag <移动标签> <目标>

通过引用teerapap / git-move-annotated-tag.sh开发了上述功能。


1
似乎不再需要它:git tag -f -a my_tag已经保留了先前消息的消息(使用git version 2.11.0)。
Matthijs Kooijman,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.