正如Don Branson在评论中指出的那样,这似乎是一个XY问题.但是Git和Mercurial中的标签有根本区别,因为Mercurial标签是文件中的条目,而Git标签是位于存储库空间之外的名称(尽管带注释的标签也包含存储库对象).
特别是,Mercurial将标记存储为名为的文件中的条目.hgtags.该条目提供标记的名称和任何其他有用的数据,包括标记的提交的哈希ID.为了将更新的.hgtags文件存入存储库,Mercurial必须在将条目添加到文件后进行新的提交.hgtags.
这有一个基本的(虽然很小)缺点:将标记的提交结果提取.hgtags到缺少标记的文件中,以便标记消失.为了弥补这一点,现代Mercurial将找到多个版本.hgtags,包括一个晚于当前提交的提交,以便在给定标记名称的情况下找到正确的提交.
相反,Git将标记存储为直接指向提交的表单的轻量级名称,或者作为指向类型的存储库对象的相同表单的轻量级名称,其中存储库对象保存标记的目标的哈希ID .这意味着创建标记不会干扰现有的存储库内容; 没有包含标签的存储库文件.refs/tags/nametag
标签的正常设计目标是标签永远不会改变,也永远不会消失:它们充当<name,hash-id>对的附加存储池(可能带有附加数据).如果标签实际上是以这种方式使用的,那么Git和Mercurial方法的行为是相同的,除了Mercurial需要Git不需要额外提交的怪癖.
在实践中,人们会犯错:他们会意外地移动标签,甚至是故意移动标签以试图掩盖早期的事故.因此水银的方法比Git标签一个基本的审计跟踪的优势,也:我们可以在任何犯,看看有什么标签都为那次提交,即使有人已经改变,因为他们随后.Git的方法的优点是,我们不能看到这一点,因此不能成为它困惑:有没有办法为标签v2.1的名字都提交a93fc12... 和 e07c1c4...,取决于其呈交我们目前签出.(请注意,由于提交仅提供部分订单,而不是总订单,因此我们可能无法使用"提交订单"在Mercurial中出现歧义的情况下选择最终获胜者.)
总而言之,如果你想在Git中创建一个新的提交,以便有一个唯一的提交哈希来标记,只需创建一个新的提交.1 虽然Git默认拒绝提交与当前提交相同的内容,但是git commit有一个标志来强制执行这样的提交:--allow-empty.(这个标志有点错误名称:新的提交不是空的,它是通过将新提交与其父项的空白进行比较而产生的更改集.)创建了一个新的提交对象后,您将拥有一个新的唯一哈希ID.
但是,使用带注释标记的轻量级名称指向新的带注释标记对象这一事实可能会更好.新标记对象就像新提交一样,保证是唯一的(再次参见脚注1).您可以像使用提交ID一样使用标记对象的哈希ID,只要系统的其余部分准备好处理标记对象并通过它间接查找提交即可.
1请注意,每次提交都会获得一个时间戳(或者更准确地说,是两个时间戳,但默认情况下,新提交会将它们都设置为相同的值).只要我们假定时间是单调递增的,这意味着,即使一个新的提交否则的复制现有的承诺,即,它具有相同的tree,相同的author和committer,同样parent,和现有的一些相同的日志消息commit-it将具有不同的时间戳,因此是不同的提交.
但是,当我们通过某些自动化机器进程进行提交时,我们可以每秒制作许多提交,即使时间表现良好,时间戳的粒度也只有一秒.这意味着在某些情况下 - 特别是当使用--allow-empty和提交与先前提交相同的父级时,例如,通过让我们的机器进程更改分支名称进行提交 - 可以创建"新"提交与旧提交完全相同的数据,以便声称新提交具有相同的哈希ID.在这种情况下,我们假设每个提交散列ID都是唯一的:它对于提交的内部数据是唯一的,但由于提交的内部数据与先前提交的内部数据匹配,因此两个提交在基本意义上是相同的,因此它们是获取相同的提交哈希ID,当我们期望它们获得不同的哈希ID时.
这意味着当我们编写代码来进行提交时,我们必须仔细检查我们的假设.对于机器制造的注释标签也是如此:我们可以让机器每秒制造许多这样的标签,因此我们应该小心确保它们的内部数据不同,而不仅仅依赖于单调增加的时间戳.
| 归档时间: |
|
| 查看次数: |
93 次 |
| 最近记录: |