我最近进入了一个项目,想要修改旧的git标签名称和消息,所以我根据stackoverflow上的几个答案进行了更新:
[3, 1]
这有效,改名,但我也想修改相应的消息,所以我做了这个:
git tag newname oldname
git tag -d oldname
git push origin :refs/tags/oldname
git push --tags
当我查看时,它似乎有效:
git tag newname newname -f -m "new message for renamed tag"
但是,当我现在尝试git tag -n1
时,我收到以下错误:
git push --tags
我现在不知道该怎么做......
1)如何解决这个问题,以便保留新的名称/消息并推送标签而不会出现故障?
2)首先要做的更好的方法是什么?
谢谢
答案 0 :(得分:1)
删除遥控器上的标签,然后再按一次以再次创建(或使用--force
一步完成)。
标签背后的想法是它永远不会改变的标签(与分支名称的想法相反,是 更改的标签) 。因此,Git通常不愿意使用现有标签并将其指向新的不同位置。
这就是更改标记时必须使用-f
(强制)标记的原因:
git tag newname newname -f -m "new message for renamed tag"
如果没有-f
,Git会抱怨标签已经存在,并且什么都不做。
由于您使用的是-m
,因此您将获得带注释的标记。这很重要,否则你不会以任何方式改变标签,也没有问题。
我在上面提到过,两个分支(更具体地说,分支名称)和标签都是标签。
像master
这样的分支名称通常通过commit-ID直接指向某个提交。因此,master
是您可以阅读并转换为提交ID的内容; git rev-parse
命令正是这样做的:
$ git rev-parse master
3ad15fd5e17bbb73fb1161ff4e9c3ed254d5b243
然而,标签名称可以直接指向提交:
$ git tag temp-tag master
$ git rev-parse temp-tag
3ad15fd5e17bbb73fb1161ff4e9c3ed254d5b243
$ git tag -d temp-tag
这称为轻量级标记。
或者,它可以指向新创建的git 对象,它表示一个标记(称为标记对象或带注释的标记对象 ,取决于谁打电话以及他们想要多么明确)。包含消息的标记或您使用-a
创建的标记会生成其中一个带注释的标记:
$ git tag -m foo temp-tag master
$ git rev-parse temp-tag
04565b0274c13ac49a70b8e34cdb9c912e02f0ab
请注意,此带注释的标记与master
具有不同的ID。它实际上由一对项组成:一个轻量级样式标记,指向存储库中带注释的标记对象;和带注释的标记对象,指向commit:
$ git cat-file -p temp-tag | sed 's/@/ /'
object 3ad15fd5e17bbb73fb1161ff4e9c3ed254d5b243
type commit
tag temp-tag
tagger Chris Torek <chris.torek gmail.com> 1461965004 -0700
foo
$ git tag -d temp-tag
请注意object
行,其中包含提交的ID。
(除此之外:尝试git cat-file -p
原始ID,包括提交ID。您会看到包含tree
ID的内容;请尝试使用git cat-file -p
,可能会通过{{1} }或less
因为它们可能相当长。另外,尝试在哈希值more
上运行git rev-parse
,同时缩短它们,例如3ad15fd5e17bbb73fb1161ff4e9c3ed254d5b243
。所有这些都很有启发性。)
对象一旦被创建,就永远不会被改变 - 不是一点点,而不是一个比特。它们可以完全删除, 1 但不会更改。因此,要移动带注释的标记,您必须删除旧标记,然后创建一个新标记,它将获得一个新的不同的哈希ID。 git rev-parse 3ad15
标志使得git只需一步即可完成。
由于标签不是假设要移动,Git(现在 2 )会检查并确保它们不会移动。要移动现有的轻量级或带注释的标记,您必须使用--force
或--force
。对于轻量级标记,这至少有效 - 删除标记(但不是提交),然后将新标记附加到新对象。对于带注释的标记,这将删除轻量级标记和基础带注释的标记对象,然后创建新的基础带注释的标记对象,并将新的轻量级标记附加到新的带注释的标记对象。
当然,您可以将其分为两个单独的步骤,这使其更加明显。
相同的规则适用于-f
。由于git push
具有git push
/ --force
,您可以将这两个步骤隐藏(并优化)为一个,但它实际上是一个删除并重新创建。
1 删除对象实际上相当复杂。 Git是围绕添加对象构建的,而不是删除它们。 垃圾收集器,-f
- 内部由一系列独立的清道夫阶段组成,所有这些都可以手动运行 - 最终真正删除了东西。
2 在1.8.2之前的Git版本中,git gc
将分支规则应用于标记,因此如果操作是快进,则可以推送标记。 1.8.2发行说明以:
“git push $ there tag v1.2.3”用于替换标签v1.2.3 已存在于存储库$中,如果重写的标记 您正在提交作为提交后代的提交 老标签v1.2.3指向。发现这很容易出错 并从此版本开始,任何更新现有的尝试 refs / tags / hierarchy下的ref将失败,没有“--force”。
答案 1 :(得分:0)
最好的方法是不删除标签,而只是将标签更新为新的提交。
# create a new annotated tag and force it to replace the old one
git tag -af <tagname> -m <message>
现在将标签推送到遥控器:
git push --follow-tags