【问题标题】:How can I move a tag on a git branch to a different commit?如何将 git 分支上的标签移动到不同的提交?
【发布时间】:2011-12-24 01:56:21
【问题描述】:

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

git tag -a v0.1

但后来我意识到仍然需要一些更改才能合并到 0.1 版的 master 中,所以我这样做了。但是现在我的v0.1 标签卡在了错误的提交上(调用便利贴类比)。我希望它停留在 master 上的最新提交上,但它却停留在 master 上的第二个最近提交上。

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

【问题讨论】:

    标签: git git-tag


    【解决方案1】:

    -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
      

    【讨论】:

    • 这仅在您没有将代码从您的机器上推送的情况下才有效。如果你有,最好的答案是“世界上有很多数字”,因为这可能不值得麻烦。
    • 如果你已经推送了你的标签,你仍然可以通过强制推送来更新远程标签git push -f origin &lt;tagname&gt;
    • 如果标签引用可以快速转发到新的地方,则不必使用强制推送。
    • 这里和文档中没有提到的是,如果没有给出新消息,这确实会移动标签消息。
    • 请注意,在#3 中git push origin master --tags 将推送标签,如果您已在本地提交任何更改,则master 分支。如果您只想推送标签,请使用git push origin --tags
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      总结一下,如果您的遥控器被称为 origin 并且您正在处理 master 分支:

      git tag -d <tagname>                  # delete the old tag locally
      git push origin :refs/tags/<tagname>  # delete the old tag remotely
      git tag <tagname> <commitId>          # make a new tag locally
      git push origin <tagname>             # push the new local tag to the remote 
      

      说明:

      • 第 1 行删除本地环境中的标记。
      • 第 2 行删除远程环境中的标记。
      • 第 3 行将标签添加到不同的提交中
      • 第 4 行将更改推送到远程

      您还可以将第 4 行更改为 git push origin --tags 以将所有本地标签更改/更新推送到远程仓库。

      以上答案基于@eedeep问题中的内容,以及Stuart GolodetzGreg Hewgill和@ben-hocking的答案,以及他们答案下方的cmets,以及我的答案下方@NateS的原始cmets .

      【讨论】:

      • 第 4 行用于将明确的 single 更新标签推送到远程存储库,以防您不想更新所有标签,因为我没有。跨度>
      【解决方案4】:

      git tag -d &lt;tagname&gt; 删除它,然后在正确的提交上重新创建它。

      【讨论】:

      • @eedeep:为了公平起见,我认为 Greg 的回应实际上更好。
      • 保持简单。删除它,再做你之前做的事情。
      • 这应该是公认的答案,因为它很简单。也不会过度使用 -f 强制。
      • @chinnychinchin。这是一个真正使用武力并不过分的地方。这与在合并期间说“接受我的”没有什么不同。
      【解决方案5】:

      我在使用 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 是示例提交。

      【讨论】:

      • 我认为 OPs 标签被注释了。第三行可能是这样的 git tag -a fix123 790a621265 # create a new local, annotaged tag
      • 我讨厌这是最好的答案。我想知道为什么它必须如此复杂?标签非常适合标记哪个提交用于生产,所以我需要经常更改它所附加的提交。使用一个你总是变基的分支目前更容易,但当环境与你的存储库内容无关时,它是多余的(值得努力)。
      【解决方案6】:

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

      $ git tag -f v0.0.1.2 63eff6a
      
      Updated tag 'v0.0.1.2' (was 8078562)
      

      然后:

      $ git push --tags --force
      

      【讨论】:

        【解决方案7】:

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

        在您的示例中,要使用哈希 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 #"
        

        【讨论】:

          【解决方案8】:

          另一种方式:

          在远程仓库中移动标签。(如果需要,将 HEAD 替换为任何其他标签。)

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

          取回更改。

          $ git fetch --tags
          

          【讨论】:

          • 这比其他答案更具“交易性”。
          【解决方案9】:

          如果你使用 github 并且想要更改 commit for release(例如你发现在创建 release 后不提交 smth)。你可以使用

          git push origin :refs/tags/<tagname>
          

          在此命令之后 github 删除您的标签,您的发布将成为草稿。这意味着您可以重新创建发布并选择提交。您的文件和消息将被保存。

          【讨论】:

            【解决方案10】:

            如果你想移动一个带注释的标签,只改变目标提交但保留注释消息和其他元数据使用:

            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开发的。

            【讨论】:

            • 似乎不再需要了:git tag -f -a my_tag 已经保留了上一条消息的消息(使用 git 版本 2.11.0)。
            猜你喜欢
            • 1970-01-01
            • 2011-07-25
            • 2013-02-20
            • 2017-05-18
            • 2011-03-11
            • 1970-01-01
            • 2014-07-17
            • 2014-11-19
            • 2016-01-04
            相关资源
            最近更新 更多