git - `git ls-remote --tags` 和 `git tag` 命令之间的标签计数差异。为什么?
问题描述
我刚刚注意到git ls-remote --tags
并git pull && git ta
返回不同的结果:
git ls-remote --tags | wc -l
: 75417
git tag | wc -l
: 75264
这种差异有什么解释吗?假设我的本地存储库仅包含一个远程(来源),并且远程存储库没有使用新标签进行更新,我希望这两个命令都返回相同的标签,但它们不会。为什么?
解决方案
您的案例是“信息过多”之一git ls-remote
在您的情况下,您确实具有相同的标签,正如您在评论中发现并提到的那样。 但这git ls-remote
只是要做的第一步git fetch
:调用另一个 Git 存储库并让它列出其分支和标签名称,以及它们相应的哈希 ID。这就是您--tags
在此处使用的原因,将列表缩减为仅标记名称。
出于git fetch
的目的,当远程列出其标记名称时,它不仅列出标记本身的内部 Git 哈希 ID,1还列出标记对象的内部 Git 哈希 ID,通常是一些提交对象。这允许git fetch
以后知道它是否已经获得了提交对象,因此应该创建相应的标签(参见下面的部分)。因此,对于这些标签中的每一种(参见脚注 1),您将获得两个输出行。带有^{}
后缀的行代表已解析的标签:请参阅gitrevisions 文档。
1 Git 的标签在内部有两种风格:轻量级标签和带注释的标签。Git引用(任何以开头的内部 Git 名称refs/
)包含 Git 对象的哈希 ID。2标记名称是以 . 开头的 引用refs/tags/
。根据定义,带注释的标签是一个标签名称,其哈希 ID 是 Git 带注释的标签对象的 ID 。Git 对象本身有四种类型:commit、tree、blob和annotated tag,因此如果标签名命名的不是带注释的标签,则该标签根据定义是轻量级标签。
带注释的标记对象本身包含另一个 Git 哈希 ID。该哈希 ID 必须是某个带注释的标记、提交、树或 blob 的 ID。所以 Git 可以取消引用这个 ID 来查找底层对象。如果那是另一个带注释的标签,Git 会根据需要继续取消引用,以找到一些非标签对象。该链最终需要通过到达一个非标签对象而结束,并且该非标签对象是标签的目标。这就是tag-name^{}
发现的。
2这忽略了 Git 所谓的符号引用,它包含另一个引用的名称而不是哈希 ID。此外,Git 的伪引用(如CHERRY_PICK_HEAD
、HEAD
、MERGE_HEAD
、ORIG_HEAD
等)不以refs/
;开头。Git 对于伪引用是引用还是其他东西有点不一致。
Git 存储库不需要具有相同的标签
不要求两个不同 Git 存储库中的标记集匹配。
的默认操作(它本身实际上是 plus 的包装器git fetch
,而直到最近实际上是一个包装器并且仍然有效)是复制指向在操作期间获取的提交的任何标记。因此,如果源存储库具有指向默认情况下未获取的提交的标签,例如,不在任何分支上,则默认情况下不会获取这些标签。那会产生你展示的那种结果。git clone
git init
git fetch
git pull
git fetch
git fetch
(请注意,如果您在本地创建标签并且不将它们推送到其他 Git,则会产生相反的效果。)
要更详细地查看事物,请将获取的标签保存在文件中,并将实际标签转储到文件中,然后比较两个文件以找出哪些标签不同。(或者,在 bash 中,使用Thomas 的建议。)
推荐阅读
- laravel - 如何使用相关表中的数据过滤查询结果?
- c# - How to switch views in a UWP application
- javascript - 搜索结果不会移动到网站的第一列 - HTML5 搜索
- java - Spring FeignClient:如何配置像 Ribbon 这样的负载均衡器
- php - 在 Laravel 中为 Godaddy webmail 配置邮件
- appcelerator - Appcelerator 动态配置
- database-design - 多人游戏数据模型设计
- mysql - 带有列标题的 Mysql 导出表到文件制表符分隔
- typescript - 找不到名称“mapStateToProps”。[2304]
- typescript - 在 Angular7 ASP .Net Core 2.1 中使用 ng2-file-upload 上传视频失败