去年,我的日常风投工作从Subversion转向了Git,现在我仍在努力把握“Git思维”的精髓。
最近困扰我的一个问题是“轻量级”、带注释的标签和签名标签。在所有实际应用中,带注释的标签都优于轻量级标签,这似乎是被普遍接受的,但我发现为什么会出现这种情况的解释似乎总是归结为“因为最佳实践”或“因为它们不同”。不幸的是,如果不知道为什么这是最佳实践,或者这些差异与我的Git使用有什么关系,这些都是非常不令人满意的论点。
当我第一次切换到Git时,轻量级标签似乎是自切片面包以来最好的东西;我可以指向一个提交并说“那是1.0”。我很难理解一个标签怎么可能需要更多,但我当然不能相信Git专家们随意地喜欢带注释的标签!那么,这些喧嚣是关于什么的呢?
(附加提示:为什么我需要在标签上签名?)
EDIT
我已经成功地相信带注释的标签是一件好事——知道谁在什么时候做了标记是很重要的!作为后续,关于好的标记注释有什么建议吗?无论是git标记-am“标记1.0”1.0,还是尝试总结提交日志,因为之前的标记感觉像是丢失了策略。
The big plus of an annotated tag is that you know who created it. Just like with commits, sometimes it's nice to know who did it. If you're a developer and you see that v1.7.4 has been tagged (declared ready) and you're not so sure, who do you talk to? The person whose name is in the annotated tag! (If you live in a distrustful world, this also keeps people from getting away with tagging things they shouldn't.) If you're a consumer, that name is a stamp of authority: that's Junio Hamano saying this version of git is hereby released.
其他元数据也很有帮助——有时知道版本是什么时候发布的,而不仅仅是最后提交的时间是很好的。有时这些信息甚至是有用的。也许这有助于解释这个特殊标签的用途。也许候选版本的标签包含一些状态/待办事项列表。
签名标签和其他任何东西都差不多——它为偏执狂提供了更高一级的安全性。我们大多数人都不会使用它,但如果你真的想在把软件安装到电脑上之前验证一切,你可能会需要它。
编辑:
As for what to write in a tag annotation, you're right - there's not always much useful to say. For a version number tag, it's implicitly understood that it marks that version, and if you're happy with your changelogs elsewhere, there's no need to put one there. In this case, it's really the tagger and date that are the most important. The only other thing I can think of is some sort of stamp of approval from a test suite. Have a look at git.git's tags: they all just say something like "Git 1.7.3 rc1"; all we really care about is Junio Hamano's name on them.
然而,对于不太明显的命名标记,消息可能变得更加重要。我可以想象为单个用户/客户端标记一个特定的特殊用途版本,一些重要的非版本里程碑,或者(如上所述)带有额外信息的发布候选版本。这样信息就有用多了。
推送带注释的标签,保持轻量级的本地
Git的某些行为确实在某些方面有所区别,这个建议是有用的,例如:
带注释的标记可以包含与它们所指向的提交不同的消息、创建者和日期。因此,您可以使用它们来描述一个发布,而不进行发布提交。
轻量级标签没有这些额外的信息,也不需要它,因为您只会在开发过程中使用它。
Git push——follow-tags只会推送带注释的标签
没有命令行选项的Git描述只能看到带注释的标记
男人说:
带注释的标记用于发布,而轻量级标记用于私有或临时对象标签。
内部差异
both lightweight and annotated tags are a file under .git/refs/tags that contains a SHA-1
for lightweight tags, the SHA-1 points directly to a commit:
git tag light
cat .git/refs/tags/light
prints the same as the HEAD's SHA-1.
So no wonder they cannot contain any other metadata.
annotated tags point to a tag object in the object database.
git tag -as -m msg annot
cat .git/refs/tags/annot
contains the SHA of the annotated tag object:
c1d7720e99f9dd1d1c8aee625fd6ce09b3a81fef
and then we can get its content with:
git cat-file -p c1d7720e99f9dd1d1c8aee625fd6ce09b3a81fef
sample output:
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
And this is how it contains extra metadata. As we can see from the output, the metadata fields are:
the object it points to
the type of object it points to. Yes, tag objects can point to any other type of object like blobs, not just commits.
the name of the tag
tagger identity and timestamp
message. Note how the PGP signature is just appended to the message
A more detailed analysis of the format is present at: What is the format of a git tag object and how to calculate its SHA?
奖金
判断一个标签是否带注释:
Git cat-file -t标签
输出提交为轻量级,标签为注解。
只列出轻量级标签:如何列出所有轻量级标签?
我发现了轻量级标签的一个很好的用途——在GitHub上创建一个版本。
我们确实发布了我们的软件,我们有必要的提交,我们只是没有费心去维护GitHub上的“发布”部分。当我们注意到这一点时,我们意识到我们也想添加一些以前的版本,并为它们提供正确的旧发布日期。
如果我们只是在旧提交上创建一个带注释的标记,GitHub将从标记对象中获取发布日期。相反,当我们为这个旧的提交创建了一个轻量级标记时,发布版开始显示正确的(旧的)日期。
来源@ GitHub帮助,“关于发布”
似乎也可以为带注释的提交指定你想要的日期,但在我看来并不那么简单:
https://www.kernel.org/pub/software/scm/git/docs/git-tag.html#_on_backdating_tags
对我来说,重要的区别是轻量级标签没有时间戳。假设你添加了几个轻量级标签:
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”,这是最后添加的标签。