Git版本和引用是如何相互关联的?

mwg9r5ms  于 2023-03-28  发布在  Git
关注(0)|答案(2)|浏览(165)

最后,修订和引用都是指向Git对象的指针,那么两者都有什么意义呢?

tf7tbtn2

tf7tbtn21#

......就是这样(?)。
就这样...差不多了
Git使用文件系统作为数据库。引用存储在两个地方之一。.git/refs.git/packed-refs
.git/refs/为每个引用都包含一个文件。例如,主分支在.git/refs/heads/main中。标签v1.2.3在.git/refs/tags/v1.2.3中。该文件包含它引用的提交的SHA。当您请求main时,git会搜索这些目录,当找到匹配的文件名时,它会从文件中读取SHA。这就是为什么您也可以将主分支称为mainheads/mainrefs/heads/main;它们只是要搜索的相对文件路径。
如果目录树中有很多引用,并且不能扩展,那么搜索目录树会变得很麻烦,尤其是在网络驱动器上。所以git偶尔会将这些引用“打包”到一个文件.git/packed-refs中。这是一个简单的文件,每个引用对应一行,格式为<sha> <ref>。Git打开文件,读取直到找到匹配的引用,然后使用sha。
这样一个小而经常被引用的文件很可能会保留在操作系统的缓存中,使得后续的读取非常快。Git会定期写一个新的packfile。
使用文件系统作为数据库而不是像SQLite或二进制文件格式这样的数据库,是一种非常快速、非常优雅且非常可移植的解决方案。
您可以在Pro Git的Git Internals章节中阅读更多关于packfilesreferences的信息。

ibrsph3r

ibrsph3r2#

TL;DR

Git引用(即Git对象的别名)可以是Git版本号(即Git对象查询)example-1,但反之则不然example-2,因为:

  • (多对一)一个ref只能代表一个单个Git对象,但每个Git对象可以有多个ref
  • (一对多)一个rev可以解析为一个或多个Git对象。

[示例-1]:git log main
[示例-2]:git log main..topic(即使修订版main..topic使用两个引用,maintopic)。

Git引用(ref s)

多对一关系:

┌─────────┐             ┌──────┐
│  Git    │ *         1 │  Git │
│reference├────────────►│object│
└─────────┘             └──────┘

Git引用指向单个Git对象****2,多个Git引用可以指向同一个Git对象

详细说明这一点:

  • Git reference是特定Git对象2的替代名称1
  • Git reference被取消引用(或解析)时,结果是一个SHA-1对象名称(40字节十六进制字符串)3在对象数据库中标识Git object
  • Git references和Git对象2多对一关系:许多引用可以指向同一个对象,但是一个引用在任何给定时间只能指向一个对象。

[1]:或“别名”、“指针”、“标签”等
[2]Git对象有4种类型:tree, blob, commit和tag。
[3]:For now,至少。
例如:

[~/my-project]$ git cat-file --batch-check --batch-all-objects
10d5ab2b502faadff680c6904cbd60d7a8b5d0af tree 34
11f61d01b7af5c657c13109777a577ef6a3d3a7a tree 34
1d41fcffd528c1ee950b630d939407fe5f3b22d0 tree 34
40267b7fcf0d4490a45e0d70618a5d7b63895a60 blob 25
5a6bdceda9ae20b80fed214776b4423f522f2d01 tree 68
5b76730490981c045b186fd9651f91f0492c5b07 blob 12
5f45e9c854941c72deb9d36fb3e95e4feb4d698f commit 234
64a77169fe44d06b082cbe52478b3539cb333d45 tree 34
6692c9c6e231b1dfd5594dd59b32001b70060f19 commit 237
740481b1d3ce7de99ed26f7db6687f83ee221d67 blob 50
83cb3ab54ca122d439bdd9997a21f399cac69692 blob 16
864333c0eccabdaba6df27166ac616c922569b47 blob 42
abb08192ed875ef73fa66029994aa2f6700befd0 commit 231
c277976fce0b2b32b954a66d4345730b5b08f1db commit 230
e67cb07f9ddb0ecd0f88fcf36093d8d8bf928b75 commit 175
e95dd8284a84af5418c0dcf9cbdc0b1061624907 blob 25

[~/my-project]$ git show-ref --head --dereference
5f45e9c854941c72deb9d36fb3e95e4feb4d698f HEAD
c277976fce0b2b32b954a66d4345730b5b08f1db refs/heads/main
5f45e9c854941c72deb9d36fb3e95e4feb4d698f refs/heads/topic
c277976fce0b2b32b954a66d4345730b5b08f1db refs/remotes/origin/main
5f45e9c854941c72deb9d36fb3e95e4feb4d698f refs/remotes/origin/topic
e95dd8284a84af5418c0dcf9cbdc0b1061624907 refs/tags/balabab
e95dd8284a84af5418c0dcf9cbdc0b1061624907 refs/tags/lofa
5f45e9c854941c72deb9d36fb3e95e4feb4d698f refs/tags/miez

Git版本号(rev s)

一对多关系

┌────────┐              ┌──────┐
│  Git   │ 1          * │  Git │
│revision├──────────────┤object│
└────────┘              └──────┘

Git revision是一个解析为一个或多个Git对象的Git对象查询。

Git版本号是一个符合a special notation syntax(或“版本号查询系统”)的字符串,用于明确选择一个或多个Git对象2
这类似于数据库系统(例如PostgreSQL)如何使用查询语言(例如SQL),但在这种情况下,Git是数据库系统,而版本语法是查询语言。这种类比似乎也适用于版本能够引用一系列Git对象。
例如,给定此提交历史,

* ebc9079 (HEAD -> main) karikittyom
* 982b806 edes
* ccccccc tyukom
* bbbbbbb megis van
* aaaaaaa egy felpenzem

修订版aaaaaaa..ccccccc将返回提交bbbbbbbccccccc

$ git log aaaaaaa..ccccccc

commit cccccccccccccccccccccccccccccccccccccccc
Author: toraritte
Date:   Mon Jan 9 03:29:24 2023 +0000

    tyukom

commit bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
Author: toraritte
Date:   Mon Jan 9 03:29:24 2023 +0000

    megis van

ref s和rev s的连接

  • Gitreferences仅仅是特定Git对象的标签 ,但很多时候你也想对其他对象执行操作。唯一的方法是手动找到它们,然后列出所有涉及的Git对象的SHA-1哈希值。
    revision表示法是一个查询系统,通过遍历有向无环图或DAG来到达repo
    中的任何Git对象(或它们的范围)。

相对5****修订查询的基本构建块是

  • 扩展SHA-1语法(例如<sha1>,例如dae86e1950b1277e545cee180551750029cfe735dae86e
  • Git references(最终解析为<sha1>

其中references用作开始遍历图形的起点。
[5]:这里使用“relative”很重要,因为还有:/<text>:\[<n>:\]<path>不需要锚。
至少,gitrevisions文档中的每个符号都可以归结为上面的结论:

  • <describeOutput>,例如v1.7.4.2-679-g3bee7fbgit describefinds the most recent tag that is reachable from a commit". tag是Git引用,git describe已经有了自己的revision-esque表示法。
  • [<branchname>]@{upstream},e.g. master@{upstream}@{u}分支名称是Git引用,其余是修订查询符号。
  • <rev>^{<type>},例如v0.99.8^{commit}其中<rev>意味着“* 在递归时取消引用对象 *”,所以最后我们将得到一个标记或<sha1>

相关问题