Git:有没有办法直接通过提交ID标记远程分支HEAD?

时间:2016-12-13 20:15:38

标签: git tags

我试图在我的Git仓库中清理掉很多死枝,但在删除任何分支之前,我想确保我已经标记了每个分支的HEAD。

我可以通过

检索所有远程分支的列表
 git ls-remote --heads origin

这将生成所有提交ID和分支名称的列表。

我现在如何为每个分支创建远程标记,而无需在本地检出每个分支,在本地创建标记并将标记推回原点?我是否必须在本地创建标签然后推送它(即:两步过程)?

例如:

git tag <branch_name_as_tag> <commitId>
git push origin <branch_name_as_tag>

有没有更清洁的方法呢?

2 个答案:

答案 0 :(得分:3)

不需要弄乱本地标签,只需在推送时进行重写。

git push origin refs/remotes/origin/*:refs/tags/tagged-*

如果您希望标签是本地的,请推送到您自己的仓库(通过路径名,.)。

答案 1 :(得分:3)

简短的回答是“也许” - 或“是”如果你真的是指你在你的例子中所说的 - 这无疑是完全无益的。

完整答案

如果您意识到git push的工作方式是:

,这可能有所帮助
  1. 调用遥控器;
  2. 发送任何所需的提交和其他对象,如果有的话;
  3. 要求它设置一些特定对象ID的特定引用;
  4. 阅读对第3步的回复,并使用它们更新本地参考文献。
  5. 除此之外,还有两种“标签”,如果您之前没有看过,我们必须定义“参考”。

    在Git中,引用只是一个几乎任意的 1 字符串,以refs/开头。但是,有几个不同的前缀构成了引用的分层名称空间。分支名称以refs/heads/开头,标记名称以refs/tags/开头,远程跟踪分支名称以refs/remotes/开头,并且还有一个级别来命名特定的远程(通常为origin/ )。

    这两种标签是轻量级带注释的标签。关键区别在于带注释的标记具有关联的存储库对象。 (这可能需要定义“对象”,但是我将把它留给一个单独的问题。现在让我们说一下annotated-tag对象中有提交哈希,以及制作标记的人的名字,以及任何PGP签名。这个标记对象有自己独立的哈希ID,就像任何提交哈希一样。)如果标记引用 - 以refs/tags/开头的名称 - 命名带注释的标记对象,则它是带注释的标记。否则它是一个轻量级标签。

    所以,当你的Git调用另一个Git时,最有趣的部分是第3步。你的Git会说:set refs/tags/v1.2 to point to object #face0ff...关键问题是:这个数字face0ff或其他什么来自哪里?

    如果您希望标记已在上游的提交,则该号码来自其Git存储库。现在,为了让你的 Git看到它,当你启动时,这个数字也必须在你的 Git存储库中,但这很容易做到:

    git fetch
    

    或:

    git fetch origin
    

    现在您拥有来自origin名称空间的refs/remotes/origin/*的所有分支及其所有提交ID,并且所有提交都安全地存储在您的存储库中。

    但是,如果您希望这些新标记为带注释的标记,则需要带注释的标记对象。您很可能必须创建新的。每个新的带注释的标记对象都应指向现有的提交。然后你可以像以前一样运行git push,但这一次,在第2步中,让你的Git向他们的Git发送这些新的带注释标签的对象。然后,您的步骤3包括要求他们将refs/tags/v1.2设置为您在第2步中发送的带注释标记对象的ID(他们使用相同的 ID)。

    您的示例git tag newtag <commitid>生成轻量级标记(对于您已经拥有的提交),因此您无需创建新的标记对象。在这种情况下,因为您可能已经拥有所有提交ID:

    git push 1234567:refs/tags/newtag
    

    您可以在命令行中列出此实例。

    但是,这样做可能更简单,更不用说容易出错了,而是这样做:

    git tag <name> <id>
    git tag <name> <id>
      ...
    git tag <name> <id>
    git push --tags origin
    

    最后一步告诉您的Git将您的 refs/tags/*推送到他们的 refs/tags/*,其中*只是匹配所有内容(包括嵌入式斜杠,因此它与shell glob *)不完全相同。他们已经拥有的标签,他们将在步骤3中跳过(因为没有更改)或在步骤3中拒绝(因为默认情况下不允许对标签进行更改)。

    1 一系列规则,保持这些不被任意。有关详细信息,请参阅the git-check-ref-format documentation。请注意,对于“存储”,唯一标准的单级引用为refs/stash