git 中的简单引用与轻量级标签

simple ref vs lightweight tags in git

我目前正在尝试了解 git 的内部结构;我的问题是轻量级标签和简单 ref 之间有什么区别? 根据我目前所读的内容,轻量级标签 实际上是一个带有标签名称的文件,其内容是一个对象 ID [我猜是一个提交对象 ID?] .在这本书'git pocket guide'中,作者说“一个简单的引用直接指向一个对象ID”;那就是我感到困惑的地方!在我看来,这些是相同的东西,但名称不同。 说轻量级标签是简单引用的特定版本是否正确?因为轻量级标签只能指向提交对象,而简单引用不仅限于提交。

A ref(或更长的变体,reference )是一个名字,在 Git 中。引用形式有多种:

  • refs/heads/xyz 分支名称 xyz;
  • refs/tags/xyz 标签名称 xyz;
  • refs/remotes/origin/xyzremote-tracking 名称,您的 Git 正在用于名为 xyz 的分支,如某些您正在调用的其他 Git 个存储库 origin;

等等。

A Git object 是四种 object 类型之一:

  • a blob object 保存数据(例如文件内容或符号 link 的目标);
  • a tree object 包含 元组,其中 mode 告诉你什么Git object hash 指定并且 name 包含名称组件(目录或文件名);
  • a commit object 保存提交的元数据,其中必须包含特定的 headers (包括恰好一个 tree 行给出一棵树的哈希 ID object:这是提交的快照);和
  • a tag object or annotated tag object 包含标签数据,就像提交一样— 必须包含特定的 headers,包括一个 object 行给出标记 object 的哈希 ID(可以是四种 object 类型中的任何一种,包括另一个带注释的标记) .

所有 object 都有一个唯一的哈希 ID。此哈希 ID 充当简单 key-value database 中的键。 Git 将使用密钥找到 object;您必须(以某种方式)提供密钥。如果您提供一个缩短的键——即键的前缀——Git 将查找该前缀找到的所有 object;如果只找到一个,则假定它是正确的完整哈希 ID,我们从那里开始;如果找到多个,则我们有一个不明确的哈希 ID(可能是其中任何一个)。

所有 refs 必须包含一些现有的有效 object 的哈希 ID。一些 object 还包含哈希 ID;这些也必须是一些现有的有效哈希 ID object.1

一些引用在它们可能包含哪些 object 类型方面受到限制:特别是,分支名称必须包含提交哈希 ID。由于 remote-tracking 名称是通过从其他 Git 存储库(应遵守同一组约束)读取分支名称而创建的,因此 remote-tracking 名称还应包含提交哈希 ID。但是,标签名称可以包含四种内部 object 类型中任何一种的哈希 ID。

一个轻量级标签refs/tags/*形式的引用——因此是一个标签名称——它包含一个有效的哈希ID,但是一个用于内部Git object 即 不是 标签 object。 带注释的标签refs/tags/* 形式的引用,其中包含 object 的有效哈希 ID,该 object 是带注释的标签 object.

is it correct to say that a lightweight-tag is a specific version of a simple ref?

大多数情况下,是的。轻量级标签是一个特定的 ref:以 refs/tags 开头(然后是斜杠和更多名称字符)的标签。但是,它还满足一个限制条件:哈希 ID 存储在 中,ref 是 object 类型不是“注释标签”的哈希 ID。


1在 so-called shallowpartial clone。 (你可以有一个既浅又部分的克隆。)散列 ID 应该是有效的,但在我们填充缺失的 objects.

之前我们无法判断它是否有效。

你是对的:轻量级标签一个简单的引用

它的主要特点是它存储在 .git/refs/tags 下,这是一个约定,表明 git 命令可以像对待标签一样对待它:

  • git tag --list会列出来,
  • git tag -d <tag_name>会删除,
  • 在某些情况下,
  • git 会将名称 refs/tags/tag_name 缩短为 tag_name
  • 等...

与 refs 相关的其他主要约定是:

  • 分支存储在 refs/heads
  • 远程引用(或远程分支)存储在 refs/remotes/<remote_name>/

这些引用也是简单的引用。


非简单引用的示例是 HEAD(存储在 .git/HEAD 中)。

您可以 运行 cat .git/HEAD 查看其内容:如果您当前在一个分支上,您应该会看到类似的内容:

$ cat .git/HEAD
ref: refs/heads/my_branch

这称为 符号引用 ,作用于 HEAD 的命令(例如:git log HEAD)将“翻译”HEADmy_branch.