我试图在我的Git仓库中清理掉很多死枝,但在删除任何分支之前,我想确保我已经标记了每个分支的HEAD。
我可以通过
检索所有远程分支的列表 git ls-remote --heads origin
这将生成所有提交ID和分支名称的列表。
我现在如何为每个分支创建远程标记,而无需在本地检出每个分支,在本地创建标记并将标记推回原点?我是否必须在本地创建标签然后推送它(即:两步过程)?
例如:
git tag <branch_name_as_tag> <commitId>
git push origin <branch_name_as_tag>
有没有更清洁的方法呢?
答案 0 :(得分:3)
不需要弄乱本地标签,只需在推送时进行重写。
git push origin refs/remotes/origin/*:refs/tags/tagged-*
如果您希望标签是本地的,请推送到您自己的仓库(通过路径名,.
)。
答案 1 :(得分:3)
简短的回答是“也许” - 或“是”如果你真的是指你在你的例子中所说的 - 这无疑是完全无益的。
如果您意识到git push
的工作方式是:
除此之外,还有两种“标签”,如果您之前没有看过,我们必须定义“参考”。
在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
。