我目前正在尝试了解 git 的内部;我的问题是轻量级标签和简单的 ref 有什么区别? 根据我目前所读到的内容,轻量级标签实际上是一个带有标签名称的文件,其内容是对象 ID [我猜是提交对象 ID?在这本书的"Git 袖珍指南"中,作者说">一个简单的引用直接指向一个对象 ID";这就是我困惑的地方!在我看来,这些是相同的东西,但命名不同。 说轻量级标签是简单引用的特定版本是否正确?因为轻量级标签只能指向提交对象,但简单引用不仅限于提交。
ref(或更长的变体,引用)是一个名称,在 Git 中。 引用有多种形式:
refs/heads/xyz
是分支名称xyz
;-
refs/tags/xyz
是标签名称xyz
; refs/remotes/origin/xyz
是您的 Git 用于名为xyz
的分支的远程跟踪名称,如您origin
调用的其他 Git 存储库中看到的那样;
等等。
Git 对象是以下四种对象类型之一:
- blob 对象保存数据(例如,文件内容或符号链接的目标);
- 树对象包含<模式、名称、哈希>元组,其中模式告诉您哈希指定的 Git 对象类型,并且名称包含名称组件(目录或文件名);
-
提交对象保存提交的元数据,其中必须包含特定的标头(包括一个
tree
行,给出一个树对象的哈希 ID:这是提交的快照);
标记对象 - 或带注释的标记对象包含标记数据,这些数据(如提交)必须包含特定的标头,包括提供标记对象的哈希 ID 的
object
行(可以是四种对象类型中的任何一种,包括另一个带注释的标记)。
所有对象都有一个唯一的哈希 ID。 此哈希 ID 充当简单键值数据库中的键。 Git 将使用密钥来查找对象;您必须提供密钥(以某种方式)。 如果您提供缩短的键(即键的前缀),Git 将查找该前缀找到的所有对象;如果只找到一个,则假定这是正确的完整哈希 ID,我们从那里继续;如果找到多个,我们有一个不明确的哈希 ID(可能是其中任何一个)。
所有引用都必须包含某个现有有效对象的哈希 ID。 某些对象还包含哈希 ID;这些也必须是某些现有有效对象的哈希 ID。1
某些引用在可能包含哪些对象类型方面受到限制:特别是,分支名称必须包含提交哈希 ID。 由于远程跟踪名称是通过从其他某个 Git 存储库读取分支名称(应遵守这组相同的约束)来创建的,因此远程跟踪名称还应包含提交哈希 ID。 但是,标记名称可以包含四种内部对象类型中的任何一种的哈希 ID。
轻量级标签是refs/tags/*
形式的引用(因此是标签名称),其中包含有效的哈希 ID,但用于不是标签对象的内部 Git 对象。带批注的标记是表单refs/tags/*
的引用,其中包含作为带注释的标记对象的对象的有效哈希 ID。
说轻量级标签是简单引用的特定版本是否正确?
大多数情况下,是的。 轻量级标签是一个特定的 ref:以refs/tags
开头的标签(然后是斜杠和更多名称字符)。 但是,它满足另一个约束:存储在该 ref中的哈希 ID 是类型不是"注释标签"的对象的哈希 ID。
1在所谓的浅克隆或部分克隆中,此约束会稍微放松。 (您可以有一个既浅层又部分的克隆。 哈希 ID 应该是有效的,但在我们填写缺失的对象之前,我们无法判断它是否有效。
你是对的:轻量级标签是一个简单的参考。
它的主要特点是它存储在.git/refs/tags
下,这是一个约定,表明 git 命令可以将其视为标签:
git tag --list
会列出来,git tag -d <tag_name>
将删除它,git
在某些情况下会将名称refs/tags/tag_name
缩短为tag_name
,- 等。。。
与引用相关的其他主要约定是:
- 分支存储在
refs/heads
远程 - 引用(或远程分支)存储在
refs/remotes/<remote_name>/
这些参考也是简单的参考。
非简单引用的一个示例是HEAD
(存储在.git/HEAD
中)。
您可以运行cat .git/HEAD
来查看其内容:如果您当前在分支上,您应该看到类似以下内容:
$ cat .git/HEAD
ref: refs/heads/my_branch
这称为符号引用,作用于HEAD
的命令(例如:git log HEAD
)会将HEAD
"翻译"为my_branch
。