为什么我应该关心轻量级标签和带注释的标签?

去年,我的日常风投工作从Subversion转向了Git,现在我仍在努力把握“Git思维”的精髓。

最近困扰我的一个问题是“轻量级”、带注释的标签和签名标签。在所有实际应用中,带注释的标签都优于轻量级标签,这似乎是被普遍接受的,但我发现为什么会出现这种情况的解释似乎总是归结为“因为最佳实践”“因为他们是不同的”。不幸的是,这些是非常不令人满意的参数,不知道它的最佳实践或这些差异是如何有关对我的Git使用。

当我第一次切换到Git时,轻量级标签似乎是自切片面包以来最好的东西;我可以指向一个提交并说“那是1.0”。我很难理解一个标签怎么可能需要更多,但我当然不能相信Git专家们随意地喜欢带注释的标签!那么,这些喧嚣是关于什么的呢?

(附加提示:为什么我需要在标签上签名?)

编辑

我已经成功的说服注释标签是一个好东西-知道谁标记和何时标记是重要的!作为后续,关于好的标记注释有什么建议吗?git tag -am "tagging 1.0" 1.0和尝试总结提交日志,因为前面的标记感觉像是丢失了策略。

61284 次浏览

默认情况下,Git只将带注释的标记作为git describe等命令的基线。将带注释的标签视为对自己和他人具有持久意义的标志,而轻量级标签更像书签,供日后自己寻找。因此,带注释的标记值得作为参考,而轻量级标记则不应该。

在标签上签名是签名者身份的保证。例如,它可以让用户验证他们获得的Linux内核代码是否与Linus Torvalds实际发布的代码相同。签名也可以是签名者在提交时担保软件质量和完整性的断言。

带注释标签的最大优点是您知道是谁创建了它。就像提交一样,有时知道是谁做的很好。如果您是一名开发人员,看到v1.7.4已被标记(声明为就绪),但您不确定,那么该向谁询问呢?名字在带注释的标签中的人!(如果你生活在一个不信任的世界里,这也会让人们避免给不该标记的东西贴上标签。)如果您是一个消费者,那么这个名字就是一个权威的标记:这是Junio Hamano在此发布这个版本的git。

其他元数据也很有帮助——有时知道版本是什么时候发布的,而不仅仅是最后提交的时间是很好的。有时这些信息甚至是有用的。也许这有助于解释这个特殊标签的用途。也许候选版本的标签包含一些状态/待办事项列表。

签名标签和其他任何东西都差不多——它为偏执狂提供了更高一级的安全性。我们大多数人都不会使用它,但如果你真的想在把软件安装到电脑上之前验证一切,你可能会需要它。

编辑:

至于在标签注释中写什么,你是对的——没有太多有用的东西可说。对于版本号标签,它被隐式地理解为它标记了该版本,如果您对其他地方的更改日志感到满意,那么就没有必要在那里放置更改日志。在这种情况下,标记符和日期才是最重要的。我唯一能想到的其他事情是来自测试套件的某种类型的批准。看看git。git的标签:他们都只是说“git 1.7.3 rc1”;我们真正关心的是朱尼奥·滨野的名字

然而,对于不太明显的命名标记,消息可能变得更加重要。我可以想象为单个用户/客户端标记一个特定的特殊用途版本,一些重要的非版本里程碑,或者(如上所述)带有额外信息的发布候选版本。这样信息就有用多了。

为标签签名是断言发布的真实性的一种简单方法。

这在DVCS中特别有用,因为任何人都可以克隆存储库并修改历史(例如通过git-filter-branch)。如果标记已签名,则签名将无法在git-filter-branch操作中存活,因此如果您有一种策略,即每个版本都由提交者标记并签名,那么就有可能在存储库中检测到虚假的发布标记。

如果不是为了签名,我也不会认为带注释的标记有多大意义。

我个人对这个话题的看法略有不同:

  • 带注释的标记是那些打算为其他开发人员发布的标记,很可能是新版本(也应该签名)。不仅可以看到谁被标记,什么时候被标记,还可以看到为什么被标记(通常是一个变更日志)。
  • 轻量级更适合私人使用,这意味着标记特殊的提交,以便能够再次找到它们。可能是为了复习它们,检查它们来测试一些东西或其他什么。

推送带注释的标签,保持轻量级的本地

Git的某些行为确实在某些方面有所区别,这个建议是有用的,例如:

  • 带注释的标记可以包含与它们所指向的提交不同的消息、创建者和日期。因此,您可以使用它们来描述一个发布,而不进行发布提交。

    轻量级标签没有这些额外的信息,也不需要它,因为您只会在开发中使用它

  • Git push—follow-tags只会推带注释的标签
  • 没有命令行选项的git describe只能看到带注释的标记

man git-tag说:

带注释的标记用于发布,而轻量级标记用于私有或临时对象标签。

内部差异

  • 轻量级标记和注释标记都是.git/refs/tags下包含SHA-1的文件

  • 对于轻量级标签,SHA-1直接指向提交:

    git tag light
    cat .git/refs/tags/light
    

    与HEAD的SHA-1相同。

    所以难怪它们不能包含任何其他元数据

  • 带注释的标记指向对象数据库中的标记对象。

    git tag -as -m msg annot
    cat .git/refs/tags/annot
    

    包含带注释的标记对象的SHA:

    c1d7720e99f9dd1d1c8aee625fd6ce09b3a81fef
    

    然后我们可以得到它的内容:

    git cat-file -p c1d7720e99f9dd1d1c8aee625fd6ce09b3a81fef
    

    样例输出:

    object 4284c41353e51a07e4ed4192ad2e9eaada9c059f
    type commit
    tag annot
    tagger Ciro Santilli <your@mail.com> 1411478848 +0200
    
    
    msg
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.4.11 (GNU/Linux)
    
    
    <YOUR PGP SIGNATURE>
    -----END PGP SIGNAT
    

    这就是它如何包含额外的元数据。我们可以从输出中看到,元数据字段是:

    更详细的格式分析在:git标签对象的格式是什么?如何计算它的SHA?

奖金

我发现了轻量级标签的一个很好的用途——在GitHub上创建一个版本。

我们确实发布了我们的软件,我们有必要的提交,我们只是没有费心去维护GitHub上的“发布”部分。当我们注意到这一点时,我们意识到我们也想添加一些以前的版本,并为它们提供正确的旧发布日期。

如果我们只是在旧的提交上创建一个带注释的标记,GitHub将从标记对象中获取发布日期。相反,当我们为这个旧的提交创建了一个轻量级标记时,发布版开始显示正确的(旧的)日期。 来源@ GitHub帮助,“关于发布” < / p > 似乎也可以为注释提交指定你想要的日期,但对我来说看起来并不那么简单: https://www.kernel.org/pub/software/scm/git/docs/git-tag.html#_on_backdating_tags < / p >

带注释的标记将额外的元数据存储为Git数据库中的完整对象,例如作者名称、发布说明、标记消息和日期。所有这些数据对于项目的公开发布都很重要。

Git标记-a v1.0.0

轻量级标记是向git存储库添加标记的最简单方法,因为它们只存储它们引用的提交的哈希值。它们可以充当提交的“书签”,因此,它们非常适合私人使用。

Git标记v1.0.0

您可以对旧标签进行排序、列出、删除、显示和编辑。所有这些函数都将帮助您识别代码的特定发布版本。我发现这篇文章可以帮助你更好地了解标签可以做什么。

对我来说,重要的区别是轻量级标签没有时间戳。假设你添加了几个轻量级标签:

git tag v1
git tag v2
git tag v3

然后,也许稍后,你想要最后添加轻量级标签。没有办法做到这一点。“git描述”和“git标签”都不会按时间顺序给出最后一个轻量级标签。"git tag -l"可以返回它们的全部或按lex顺序排序,但不能按日期/时间排序。"git describe——tags"将返回"v1",这肯定不是最后添加的标签。

另一方面,如果你添加带注释的标签:

git tag v1 -m v1
git tag v2 -m v1
git tag v3 -m v1

你总是可以得到每个标签的时间戳,“git describe”肯定会返回“v3”,这是最后添加的标签。