将标签向前一次提交


76

我的存储库只有一个分支(master)。我是我的回购的唯一贡献者。

我最近tag在本地添加了一个,并将其推送到GitHub。在完成了我的最后一次提交之后,但是现在我意识到我应该再进行一次更改/提交。

所以我有:

commit 124
commit 125
commit 126 <-- tag v1.0
commit 127

并且我想将v1.0标签移动到下一个提交,即127本地和GitHub中。

我怎样才能做到这一点?


3
推入历史记录(或标签)后,您就无法对其进行修改,实际上您可以,但是您将重写历史记录,这是很糟糕的。处理它并创建一个新的版本标签,例如v1.0.1或类似的东西。
KurzedMetal 2014年

2
@Gabriel,不,那等于同一件事。KurzedMetal建议您保留旧标签,然后添加一个标签,也许v1.0.1。我同意这是正确的方法。
克里斯(Chris

2
@Gabriel,建议不是“ Git无法移动标签,因此您必须通过删除标签并再次添加来伪造它”。它是“修改已发布的标签通常不是一个好主意,并且可能导致问题,因此您应该避免这样做”。
克里斯(Chris

1
我是回购协议的唯一贡献者。现在,也许吧,但是如果其他人可以访问您的存储库(例如,如果它是公共的),那么人们可能已经分叉或克隆了它。
jub0bs 2014年

2
@ Jubobs:到目前为止,还没有分叉(Github让您知道),我怀疑是否有任何克隆,但这是一个公平的观点。
加百利2014年

Answers:


153

您是否去过会员不都使用同一版本的“一周之书”的读书俱乐部?这是一场噩梦,对吧?移动标签实际上会使您处于相同的情况。

如果您将存储库视为一本记录项目进展的书,则可以将标签视为章标题

在此处输入图片说明

共享标签后将标签移至其他提交就像告诉所有读书俱乐部的好友

你们知道吗,伙计们?到目前为止,我们大家一直在使用的这本书的版本已经过时了,因为我只是命令第8章现在开始,而不是在126页上,而是在128页上。

不好。移动标签是重写历史记录的一种形式,您不应该重写已共享的历史记录。这是惹恼您的合作者的最可靠方法。另外,你写

我是我的仓库的唯一贡献者[...]

目前可能是正确的,但是如果您之外的其他人可以访问GitHub存储库(例如,它是公共的),那么其中一些人可能已经分叉或克隆了它(尽管有找到方法),然后您运行重写历史记录可能会惹恼他们。


如果您100%确定无论如何都要移动该标签,Git确实允许您执行此操作。在这里,您可以使用

git tag --force v1.0 <ID-of-commit-127>

然后您必须使用

git push --force --tags

但是再次,请三思而后行...

附录(2018/09/26)

我觉得有必要重新审视我的答案...

多年以来,有人在我的禁令评论中反对不要移动已经发布的标签。当然,这条建议是上下文相关的,而不是通用的。我毫不怀疑存在移动已发布标签的良好案例。但是,我坚信,作为一般规则,对发布的标签进行移动的决定应刻意且极其谨慎。

我想到了一个最近的例子。Go 1.11添加了对模块系统的实验性支持,该模块系统严重依赖于Git标签进行版本控制。在已发布的Go模块中移动标签(例如,在GitHub上)将带来灾难性的后果。

这样做会破坏您(模块作者)和用户(依赖于模块的用户)之间建立的契约,因为您将否定Go的模块系统打算提供的保证:

模块记录精确的依赖要求并创建可复制的构建。

这是让人们生气的一种肯定方法。

这个例子可能足以说服您,至少在某些情况下,您不应该无意间移动已发布的标签。我休息一下


11
这太笼统了。想象一个打包系统,它捕获了一大堆项目的快照并创建了一大堆项目。项目作者可以使用移动标签来传达他们建议纳入的修订版本。具有覆盖历史记录的分支比“ git fetch --tags”引起更多的头痛。现在,此用例缺少的一点是git可以保留标签的历史记录,即,具有相同名称的更高版本的标签可以遮盖以前的版本,但是所有这些在历史记录中仍然可见。
阿提拉·伦德瓦

21
我是那种只在乎工具有用而不是在意工具的人。
Attila Lendvai '16

2
@AttilaLendvai当然,但是对于条件意味着什么的工具对它有用:)
jub0bs 16-4-13

5
哈哈!“眼泪池”-一定是关于Git的书,对吧!?
史蒂夫·艾农

2
该答案描述了一种使用标签的方式以及在使用标签时导致问题的移动标签的方式。但是它错过了git中标签的通用功能。您可以随意创建一个名为“ FAV”而不是“ 1.1.2”的标签。相同的提交,两个标签。移动FAV很有意义。移动1.1.2不会。深入了解您在做什么,以及更深入地使用您所使用的工具。然后,您可以从这样的答案中获取有用的信息(移动标签的git命令是什么?)并丢弃其余的信息(其他所有信息)
。– 6cef

23

通常不建议移动标签,因为由于Git的高度分布性质,它可能会引起问题。考虑:

  • v1.0在提交时推送标签abcd123
  • 您的好友,称他为弗雷德(Fred),
  • 弗雷德现在v1.0abcd123
  • 您移动标签v1.0以提交cccc222并推送
  • 可能发生以下情况:
    • Fred获取了,但是v1.0服务器上的标签与他的本地v1.0标签不匹配,因此即使他没有做任何引起冲突的操作,Fred也必须手动解决此冲突
    • 弗雷德(Fred)推动了--tags添加some-tag他创建的新标签的选项;此推送被服务器拒绝,因为他的本地v1.0标签和服务器的v1.0标签不一致

如果有两个以上的开发人员,这将变得更加复杂。如果甚至没有一个人采取步骤更新他或她的本地标签,你也会遇到麻烦

如果您仍然确定要移动标签(也许这是一个开发人员项目,或者您确定没有人拿到标签,或者您准备与所有其他开发人员进行通信并确保他们会更新其本地标签),您可以执行以下操作:

git tag -a -f v1.0 <new-commit-hash>
git push --tags --force

应鼓励其他开发人员删除其标签的本地副本并获取新的标签:

git tag -d v1.0
git fetch --tags

重要说明:git push --tags --force将强制更新原始存储库中本地存储库中的每个标签
Ogre Psalm33年

5

您也可以删除标签,然后重新创建,这不需要重写历史记录。
(没有push --force

删除本地和远程

git tag -d <tag_name>
git push origin :refs/tags/<tag_name>

重新建立

git tag <tag_name>
git push --tags

2
对于已经将带标记的提交拉到本地计算机(或分支的远程服务器)的任何人,这仍然会引起冲突。您的答案实际上与先前给出的答案相同。移动或删除标签确实会更改历史记录,因为标签本质上是提交编号的“别名”。您已更改标签引用的提交号。更糟糕的是,正如其他更详细的答案所指出的那样,其他人的本地存储库中的标记现在引用的提交与本地存储库和更改后的远程存储库不同。这导致冲突和混乱。
SherylHohman

1
尽管您正确地说与移动标签相比,结果没有任何变化,但我想说删除对于您的意图是非常明确的。
Scott Prive
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.