如何创建包含特定提交记录的标签并将其推送到远程仓库?

31

假设目前我的gerrit日志如下所示:

  • commit10 (主干)
  • commit9
  • commit8
  • commit7
  • commit6 v1.72.0
  • commit5
  • commit4 v1.71.0
  • commit3
  • commit2
  • commit1

我的目标是创建一个新的标签(v1.73.0),包含commit8和commit9并将其推送到源。我被告知可以基于最新的稳定标签创建一个新的本地分支,并挑选必要的提交,然后给它打上标签。但是,我在将标签推送到主干时遇到了一些问题。

这是我做的事情:

  • 基于最新的标签创建本地分支:git checkout -b branchforv1.73.0 v1.72.0
  • 挑选commit8和commit9
  • 创建新标签:git tag v1.73.0

...现在,我应该如何将v1.73.0推送到主干?

结果:

  • commit10 (主干)
  • commit7
  • commit9 v1.73.0
  • commit8
  • commit6 v1.72.0
  • commit5
  • commit4 v1.71.0
  • commit3
  • commit2
  • commit1

1
一个新的标签(v1.73.0),应该包含 commit8 和 commit9。一个标签不能指向多个提交;只能指向一个。 - jub0bs
当你说“push it to master”时,你是指“push it to origin”(或其他远程仓库)吗? - Chris
我是指“将其推送到源”。 - aznmunkey
5个回答

80

标签(Tag)的工作原理

在Git中,每个标签都指向一个(单一的)提交。实际上,分支也是如此:一个分支名也只是指向一个提交。

使这种工作方式成为可能的有两个因素:

  • 每个提交也指向另一个提交(或者可能是几个),以及
  • 对于分支(仅限于分支),它所指向的提交会自动“向前移动”。也就是说,当你添加新的提交时——从某种意义上来说,这就是Git主要做的事情:将新的提交添加到它的集合中,有点像《星际迷航》TNG系列中的博格(Borg)一样——无论你在哪个分支上,该分支都会被重新调整为指向新的提交。

因此,分支和标签之间的主要区别在于标签不会移动。

为了看到这是如何工作的,请考虑一个只有三个提交的简单Git存储库。让我们把这些提交标记为ABC。第一个提交(A)没有指向任何东西,因为它是第一个提交,分支master指向A

A   <-- master

当你进行第二次提交时,Git 会创建一个指向 AB,并将分支名称推进到指向 B

A <- B   <-- master

当你提交第三次时,Git会将其指向其父提交,并推进该分支:

A <- B <- C   <-- master

如果您现在创建一个标签,该标签默认会指向提交C

A <- B <- C   <-- master
          ^
          |
   tag: sometag

如果您随后创建了一个新的提交D,Git 会推进分支,但不会推进标签:

A <- B <- C <- D   <-- master
          ^
          |
   tag: sometag
您可以随时创建或删除指向特定提交的任何标签:
$ git tag -d sometag

将删除标签sometag,之后:

$ git tag sometag master~2

将添加一个指向提交Bsometag标签。1

(我们刚刚证明了标签可以移动。真正的区别在于,不期望标签移动,而期望分支移动;Git 不会自动移动标签。2 分支通常期望以“前进”的方式移动,即如果master曾经指向提交C,现在指向提交D ,则通常应该通过从D开始向后工作来找到提交C。 每当您移动分支以违反此规则时,您都在“重写历史记录”;关于什么情况下这是可以接受的,什么情况会给人们带来麻烦,请参见其他文章。)

推送标签

使用git push时,实际上是命令其他 git 存储库获取你所拥有的任何新提交,并设置一些名称 - 通常是分支和/或标签 - 以指向结果集合中的某些提交(每个提交一个)。3 这些名称(分支、标签等)通常被称为“引用”,但现在我们只使用“分支”和“标签”。

git push后的参数指定要推送到的存储库(通常通过“remote”名称,如origin)。如果您省略它,Git 将尝试找到一个存储库,但是如果要添加分支或标签名称,则需要明确包含它,因为这里的第一个单词被认为是远程名称。 (也就是说,git push master 尝试使用 master 作为远程名称而不是分支名称。)

要推送所有标签,只需将--tags添加到git push命令中:

git push --tags origin

要推送一个特定的标签,你可以给它命名:

git push origin sometag

就像你可以推送一个特定的分支一样:

git push origin master
事实上,第四个参数是一对名称,例如master:mastersometag:sometag,但在大多数情况下默认情况下两边使用相同的名称。4 如果您不需要使用名称origin来使所有参数生效,例如git push --tagsgit push --tags origin相同(假设您所有的推送都是到origin),则可以省略它。
将标签设置到远程仓库中,首先要本地设置标签:git tag name commit-identifier。使用任何您喜欢的查看器确保已正确设置。然后,使用git push origin namegit push --tags将其推送上去。 1master~2语法指示git从通过master找到的提交开始,然后向后退两步。您也可以在此处编写提交B的原始SHA-1。 2旧版的git(版本号小于1.8.4)在推送时错误地将分支规则应用于标签(在远程端,即如果标签是“快速向前”的话就会移动)。 3在某些情况下,您可以将名称指向“带注释的标签”,但是没有什么阻止名称指向“树”或“blob”对象,但这不是常规设置。 4实际上,分支的默认dst refspec很复杂:它取决于您的push.default配置,是否有remote.repository.push设置和是否已配置上游等等。对于标签,规则较简单,因为没有“上游”的概念。

有关标签指向的分支,是否有任何约定?我可以让标签指向不同的分支,还是只能指向“master”分支? - Amy Pellegrini
1
@AmyPellegrini:标签不会指向分支。一旦创建标签,任何分支都是无关紧要的。标签指向提交。请参见答案中的更新图示。 - torek
@torek,是的,我明白了,我只是想知道您如何以一致的方式组织标签以启用自动发布/部署。我原本认为发布是从特定分支而不是标签触发的,但标签似乎更方便。基本上,我希望每个标签与特定版本匹配,并且每个版本默认情况下都会自动发布到给定环境。 - Amy Pellegrini
1
@AmyPellegrini 嗯,这取决于您的发布流程。不能随意地说“使用X流程”。我喜欢的一个流程是在2015年左右创建了一个名为release/1.0的分支,然后创建了一个标签名为release/1.0.rc0。修复一些错误并标记release/1.0.rc1,以此类推,直到我们有了实际的发布版本。然后,我们会删除 release/1.0 分支,因为您不能在其上进行开发:相反,有一个新的指向标记为release-1.0的提交的分支release/1.1 - torek
1
我们经过了几次更改名称的迭代,最终使用 rc/x.y 作为分支和/或标签名称,而不是 release/,直到发生发布,并将最终发布标签称为 release/x.y。这样实际的发布就被分组在一起,远离分支。但是这家初创公司资金耗尽,所以这从未超过 0.x 版本。 :-) - torek

42

这里有一个具体的例子:

git add .
git commit -m "some description"
git tag v0.1.9 # or any other text
git push origin master # push the commit
git push --tags origin # push the tags

2
git push --tags origin 已经推送了所有本地标签。我们能指定要推送的标签吗? - Mohammad Faisal

5

这就是你想要的

git add .
git commit -m "commit10"
git tag -a v1.73.0 -m "Latest release (or some message)"
git push origin master
git push origin v1.73.0

3

一旦您创建了标记(看起来您已经完成了此操作),只需运行

git push --tags origin

我尝试了那个方法,但它并没有按预期工作。不管怎样,感谢您的帮助,但我采用了另一种方式:创建一个带有最新标签的远程分支,将该分支拉到我的本地,挑选提交记录,将该分支推送,创建并推送一个新标签。 - aznmunkey

2

创建标签很简单,这里有一个命令可以完成:

示例:

git tag -a v1.0 7cceb02 -m "Your message here"

其中7cceb02是提交ID的开头部分。

然后,您可以使用git push origin v1.0推送标签。

您可以执行git log以显示当前分支中的所有提交ID。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接