.git 目录中有什么?

好吧,我想你们中的大多数人每天都或多或少地使用 git,但是您是否研究过 git 创建的 .git 文件夹中的内容?本文[1]我们将一起探索一下,了解里面到底发生了什么。

git 在基本层面上只是一堆通过文件名相互链接的文本文件。

init

众所周知,我们从 git init 开始我们的 git 之旅。这给出了我们现在可能已经习惯的信息,特别是如果你开始并放弃了很多副项目。

Initialized empty Git repository in /home/meain/dev/src/git-talk/.git/

让我们看看目前 .git 存储库中有什么。

$ tree .git

.git
├── config
├── HEAD
├── hooks
│   └── prepare-commit-msg.msample
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

它似乎创建了一堆文件和文件夹。这些都是什么?让我们一一回顾一下。

  • config 是一个文本文件,其中包含当前存储库的 git 配置。如果你仔细研究它,你会看到你的存储库的一些基本设置,如作者、文件模式等。
  • HEAD 包含存储库的当前头。根据您设置的“默认”分支,它将是 refs/heads/master 或 refs/heads/main 或您设置的任何其他分支。正如您可能已经猜到的,这指向您可以在下面看到的 refs/heads 文件夹,并指向一个名为 master 的文件,该文件目前还不存在。该文件主文件仅在您第一次提交后才会显示。
  • hooks 包含可以在 git 执行任何操作之前/之后运行的任何脚本。
  • objects包含 git 对象,即存储库中有关文件、提交等的数据。
  • refs 存储引用(指针)。 refs/heads 包含指向分支的指针,refs/tags 包含指向标签的。

add

现在您已经了解 .git 中的初始文件集是什么,让我们执行第一个操作,将某些内容添加到 .git 目录中。让我们创建一个文件并添加它(我们还没有提交它)。

echo 'meain.io' > file
git add file

这会执行以下操作:

--- init       2024-07-02 15:14:00.584674816 +0530
+++ add        2023-07-02 15:13:53.869525054 +0530
@@ -3,7 +3,10 @@
 ├── HEAD
 ├── hooks
 │   └── prepare-commit-msg.msample
+├── index
 ├── objects
+│   ├── 4c
+│   │   └── 5b58f323d7b459664b5d3fb9587048bb0296de
 │   ├── info
 │   └── pack
 └── refs

如您所见,这会导致两个主要变化。它修改的第一件事是索引文件。索引存储有关当前暂存内容的信息。这用于表示名为 file 的文件已添加到索引中。

第二个也是更重要的变化是在其中添加了一个新文件夹objects/4c和一个文件5b58f323d7b459664b5d3fb9587048bb0296de。

文件里有什么?

这是我们详细了解 git 如何存储内容的地方。让我们首先看看其中存在哪些类型的数据。

$ file .git/objects/5c/5b58f323d7b459664b5d3fb9587048bb0296de
.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de: zlib compressed data

嗯,但是 zlib 压缩数据是什么?

$ zlib-flate -uncompress <.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de
blob 9\0meain.io

看起来它包含我们执行 git add 的名为 file 的文件的类型、大小和数据。在本例中,数据表明它是一个大小为 9 的 blob,内容是 meain.io。

文件名是什么?

嗯,好问题。它来自于内容的sha1。如果您获取 zlib 压缩数据并通过 sha1sum 进行管道传输,您将获得文件名。

$ zlib-flate -uncompress <.git/objects/4c/5b58f323d7b459664b5d3fb9587048bb0296de|sha1sum
4c5b58f323d7b459664b5d3fb9587048bb0296de

git 获取要写入的内容的 sha1,获取前两个字符(在本例中为 4c),创建一个文件夹,然后使用其余部分作为文件名。 git 从前两个字符创建文件夹,以确保单个对象文件夹下没有太多文件。

向 git cat 文件问好

事实上,由于这是 git 中比较重要的部分之一,因此 git 还有一个管道命令来查看对象的内容。您可以使用 git cat-file,其中 -t 表示类型,-s 表示大小,-p 表示内容。

$ git cat-file -t 4c5b58f323d7b459664b5d3fb9587048bb0296de
blob

$ git cat-file -s 4c5b58f323d7b459664b5d3fb9587048bb0296de
9

$ git cat-file -p 4c5b58f323d7b459664b5d3fb9587048bb0296de
meain.io

commit

现在我们知道添加文件时会发生什么变化,让我们通过提交将其提升到一个新的水平。

$ git commit -m 'Initial commit'
[master (root-commit) 4c201df] Initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 file

以下是发生的变化:

--- init        2024-07-02 15:14:00.584674816 +0530
+++ commit      2023-07-02 15:33:28.536144046 +0530
@@ -1,11 +1,25 @@
 .git
+├── COMMIT_EDITMSG
 ├── config
 ├── HEAD
 ├── hooks
 │   └── prepare-commit-msg.msample
 ├── index
+├── logs
+│   ├── HEAD
+│   └── refs
+│       └── heads
+│           └── master
 ├── objects
+│   ├── 3c
+│   │   └── 201df6a1c4d4c87177e30e93be1df8bfe2fe19
 │   ├── 4c
 │   │   └── 5b58f323d7b459664b5d3fb9587048bb0296de
+│   ├── 62
+│   │   └── 901ec0eca9faceb8fe0a9870b9b6cde75a9545
 │   ├── info
 │   └── pack
 └── refs
     ├── heads
+    │   └── master
     └── tags

哇,看来有很多变化。让我们一一浏览它们。第一个是新文件 COMMIT_EDITMSG。顾名思义,它包含(最后的)提交消息。

如果您在不带 -m 标志的情况下运行 git commit 命令,那么 git 获取提交消息的方式是使用 COMMIT_EDITMSG 文件打开编辑器,让用户编辑提交消息,一旦用户更新并退出编辑器,git 使用文件的内容作为提交消息。

它还添加了一个全新的文件夹日志。这是 git 记录存储库中所有提交更改的一种方式。您将能够在此处看到所有引用和 HEAD 的提交更改。

对象目录也进行了一些更改,但我希望您首先查看 refs/heads 目录,其中我们现在有文件 master.txt。您可能已经猜到这是对 master 分支的引用。让我们看看里面有什么。

$ cat refs/heads/master
3c201df6a1c4d4c87177e30e93be1df8bfe2fe19

看起来它指向新对象之一。我们知道如何观察物体,让我们这样做吧。

$ git cat-file -t 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19
commit

$ git cat-file -p 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19
tree 62902ec0eca9faceb8fe0a9870b9b6cde75a9545
author Abin Simon <mail@meain.io> 1688292123 +0530
committer Abin Simon <mail@meain.io> 1688292123 +0530

Initial commit

你也可以这样做 git cat-file -t refs/heads/master

嗯,看起来那是一种新的对象。这似乎是一个提交对象。提交对象的内容告诉我们,它包含一个哈希值为 62902ec0eca9faceb8fe0a9870b9b6cde75a9545 的树对象,它看起来像我们提交时添加的另一个对象。提交对象还包含有关作者和提交者是谁的信息,在本例中都是我。最后还显示了此提交的提交消息是什么。

现在让我们看看树对象包含什么。

$ git cat-file -t 62902ec0eca9faceb8fe0a9870b9b6cde75a9545
tree

$ git cat-file -p 62901ec0eca9faceb8fe0a9870b9b6cde75a9545
100644 blob 4c5b58f323d7b459664b5d3fb9587048bb0296de    file

树对象将以其他树和 blob 对象的形式包含工作目录的状态。在本例中,由于我们只有一个名为 file 的文件,因此您只会看到一个对象。如果您看到的话,该文件指向我们执行 git add 文件时添加的原始对象。

这是更成熟的仓库的树的样子。更多的树对象用于从提交对象链接的树对象内部来表示文件夹。

$ git cat-file -p 2e5e84c3ee1f7e4cb3f709ff5ca0ddfc259a8d04
100644 blob 3cf56579491f151d82b384c211cf1971c300fbf8    .dockerignore
100644 blob 02c348c202dd41f90e66cfeb36ebbd928677cff6    .gitattributes
040000 tree ab2ba080c4c3e4f2bc643ae29d5040f85aca2551    .github
100644 blob bdda0724b18c16e69b800e5e887ed2a8a210c936    .gitignore
100644 blob 3a592bc0200af2fd5e3e9d2790038845f3a5cf9b    CHANGELOG.md
100644 blob 71a7a8c5aacbcaccf56740ce16a6c5544783d095    CODE_OF_CONDUCT.md
100644 blob f433b1a53f5b830a205fd2df78e2b34974656c7b    LICENSE
100644 blob 413072d502db332006536e1af3fad0dce570e727    README.md
100644 blob 1dd7ed99019efd6d872d5f6764115a86b5121ae9    SECURITY.md
040000 tree 918756f1a4e5d648ae273801359c440c951555f9    build
040000 tree 219a6e58af53f2e53b14b710a2dd8cbe9fea15f5    design
040000 tree 5810c119dd4d9a1c033c38c12fae781aeffeafc1    docker
040000 tree f09c5708676cdca6562f10e1f36c9cfd7ee45e07    src
040000 tree e6e1595f412599d0627a9e634007fcb2e32b62e5    website

change

让我们对文件进行更改,看看它是如何工作的。

echo 'blog.meain.io' > file
$ git commit -am 'Use blog link'
[master 68ed5aa] Use blog link
 1 file changed, 1 insertion(+), 1 deletion(-)

它的作用如下:

--- commit      2024-07-02 15:33:28.536144046 +0530
+++ update      2023-07-02 15:47:20.841154907 +0530
@@ -17,6 +17,12 @@
 │   │   └── 5b58f323d7b459664b5d3fb9587048bb0296de
 │   ├── 62
 │   │   └── 901ec0eca9faceb8fe0a9870b9b6cde75a9545
+│   ├── 67
+│   │   └── ed5aa2372445cf2249d85573ade1c0cbb312b1
+│   ├── 8a
+│   │   └── b377e2f9acd9eaca12e750a7d3cb345065049e
+│   ├── e5
+│   │   └── ec63cd761e6ab9d11e7dc2c4c2752d682b36e2
 │   ├── info
 │   └── pack
 └── refs

好吧,我们添加了 3 个新对象。其中之一是包含文件新内容的 blob 对象,一个是树对象,最后一个是提交对象。

让我们从 HEAD 或 refs/heads/master 再次追踪它们。

$ git cat-file -p refs/heads/master
tree 9ab377e2f9acd9eaca12e750a7d3cb345065049e
parent 3c201df6a1c4d4c87177e30e93be1df8bfe2fe19
author Abin Simon <mail@meain.io> 1688292975 +0530
committer Abin Simon <mail@meain.io> 1688292975 +0530

Use blog link

$ git cat-file -p 9ab377e2f9acd9eaca12e750a7d3cb345065049e
100644 blob e5ec63cd761e6ab9d11e7dc2c4c2752d682b36e2    file

$ git cat-file -p e6ec63cd761e6ab9d11e7dc2c4c2752d682b36e2
blog.meain.io

那些关注的人可能已经注意到,提交对象现在有一个名为parent的附加键,它链接到先前的提交,因为此提交是在先前的提交之上创建的。

branch

我们是时候创建一个分支了。让我们使用 git branch fix-url 来做到这一点。

--- update      2024-07-02 15:47:20.841154907 +0530
+++ branch      2023-07-02 15:55:25.165204941 +0530
@@ -27,5 +28,6 @@│   └── pack└── refs├── heads
+    │   ├── fix-url│   └── master└── tags

这会在 refs/heads 文件夹下添加一个新文件,其中文件作为分支名称,内容作为最新提交的 id。

$ cat .git/refs/heads/fix-url
68ed5aa2372445cf2249d85573ade1c0cbb312b1

这几乎就是创建分支的全部内容。 git 中的分支确实很便宜。标签的行为方式也相同,只不过它们是在 refs/tags 下创建的。

在logs目录下也添加了一个文件,用于存储类似于master分支的提交历史数据。

检查分支

在 git 中签出是指 git 获取提交的树对象并更新工作树中的文件以匹配其中记录的状态。在这种情况下,由于我们从 master 切换到 fix-url,两者都指向相同的提交和底层树对象,因此 git 在工作树中没有任何事情可做。

git checkout fix-url

当您在 .git 中进行签出时发生的唯一变化是 .git/HEAD 文件现在将指向 fix-url。

$ cat .git/HEAD
ref: refs/heads/fix-url

如果我们在这里,做出commit。我需要这个来展示稍后合并的作用。

echo 'https://blog.meain.io'>file
$ git commit -am 'Fix url'

合并

主要有3种合并方式。

  1. 最简单也是最容易的就是快进合并。在这种情况下,您只需更新一个分支指向另一个分支指向的提交。这几乎涉及将 refs/heads/fix-url 中的哈希复制到 refs/heads/master。
  2. 第二个是变基合并。在这种情况下,我们首先将更改应用到 main 当前一次指向一个提交的内容之上,然后执行类似于快进合并的操作。
  3. 最后一种是使用单独的合并提交来合并两个分支。这有点不同,因为它的提交对象中有两个父条目。我们将在最后进一步讨论这一点。

首先让我们看看合并之前的图表是什么样子的。

git log --graph --oneline --all
* 42c6318 (fix-url) Fix url
* 67ed5aa (HEAD -> master) Use blog link
* 3c201df Initial commit

现在执行合并:

$ git merge fix-url # updates refs/heads/master to the hash in refs/heads/fix-url

$ git log --graph --oneline --all
* 42c6318 (HEAD -> master) (fix-url) Fix url
* 67ed5aa Use blog link
* 3c201df Initial commit

push

现在我们已经使用本地 git 存储库一段时间了,让我们看看推送它时会发生什么。什么正在发送到另一端的 git 存储库?

为了展示这一点,首先让我创建另一个 git 存储库,它可以用作此存储库的远程。

$ mkdir git-talk-2
cd git-talk-2 && git init --bare

cd ../git-talk && git remote add origin ../git-talk-2

现在push

$ git push origin master

让我们看看我们的仓库发生了什么变化。

--- branch 2023-07-02 15:55:25.165204941 +0530
+++ remote 2023-07-02 17:41:05.170923141 +0530
@@ -22,12 +29,18 @@
 │   ├── e5
 │   │   └── ec63cd761e6ab9d11e7dc2c4c2752d682b36e2
 │   ├── info
 │   └── pack
 ├── ORIG_HEAD
 └── refs
     ├── heads
     │   ├── fix-url
     │   └── master
+    ├── remotes
+    │   └── origin
+    │       └── master
     └── tags

它添加了一个新的 refs/remotes 来存储有关不同remote中所有可用内容的信息。

但是什么会被发送到另一个 git 存储库呢?它是对象中和引用下的所有内容。这就是其他 git 实例获取整个 git 历史记录所需的全部内容。

Reference

[1]

Source: https://blog.meain.io/2023/what-is-in-dot-git/

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/112013.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware下linux中ping报错unknown host的解决办法

一、错误截图 二、解决办法 2.1 按照步骤查看本机虚拟IP 依次点击&#xff1a;【编辑】》【虚拟网络编辑器】&#xff0c;选中NET模式所属的行&#xff0c;就能看到子网地址。 比喻&#xff0c;我的子网地址是&#xff1a;192.168.18.0 那么&#xff0c;接下来要配置的linux…

根据pid查看jar包(windows)

打开jdk/bin/jvisualvm.exe,根据pid找到jar包的主启动类,jdk14以后不再默认使用,官网下载,也可以使用老版本的查看

如果Domino上的邮件无法直接发送到@outlook.com

大家好&#xff0c;才是真的好。 目前将Domino仅仅作为邮件服务器的企业用户还不少。如果Domino服务器版本比较新&#xff08;例如版本为11.0.x、12.0.x等&#xff09;&#xff0c;外发邮件时&#xff0c;没有通过邮件网关中转邮件&#xff0c;而是直接发送到Internet互联网上…

未来数字化转型发展的前景如何,企业又该怎么实现?

商业世界有一个认识&#xff0c;互联网只用看中国和美国&#xff0c;其他国家已经被远远甩在了后边&#xff0c;移动互联网的出现更是将互联网的跨地域、跨国、互联等属性发挥到了极致&#xff0c;让众多互联网巨头开启了争夺世界各国市场的脚步。 移动互联网的飞速发展以及物…

VMware——Window11安装VMware17(图解版)

目录 一、VMware17百度云下载二、安装三、注册 一、VMware17百度云下载 下载链接&#xff1a;https://pan.baidu.com/s/1dv_Y7ig2LUFxeHvrG2rOTA 提取码&#xff1a;elih 二、安装 下载 VMware-workstation-full-17.0.2-21581411.exe 安装包后&#xff0c;右键以管理员身份运…

LeetCode 3 无重复字符的最长子串

题目描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2: 输入: s "bbbbb" 输出: 1 解…

软考-访问控制技术原理与应用

本文为作者学习文章&#xff0c;按作者习惯写成&#xff0c;如有错误或需要追加内容请留言&#xff08;不喜勿喷&#xff09; 本文为追加文章&#xff0c;后期慢慢追加 by 2023年10月 访问控制概念 访问控制是计算机安全的一个重要组成部分&#xff0c;用于控制用户或程序如…

PHP的学习入门建议

学习入门PHP的步骤如下&#xff1a; 确定学习PHP的目的和需求&#xff0c;例如是为了开发网站还是为了与数据库交互等。学习PHP的基础语法和程序结构&#xff0c;包括变量、数据类型、循环、条件等。学习PHP的面向对象编程&#xff08;OOP&#xff09;概念和技术。学习与MySQL…

测试用例编写详解

一、前言 测试用例的编写需要按照一定的思路进行&#xff0c;而不是想到哪写到哪&#xff0c;一般测试机制成熟的公司都会有公司自己自定义的测试用例模板&#xff0c;以及一整套的测试流程关注点&#xff0c;当然我们自己在测试生涯中也应当积累一套自己的测试框架&#xff0…

【Proteus仿真】【Arduino单片机】蜂鸣器

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用蜂鸣器等。 主要功能&#xff1a; 系统运行后&#xff0c;蜂鸣器播放音乐。 二、软件设计 /* 作者&#xff1a;嗨小易&#xff08;QQ&#x…

什么是CSS的外边距重叠?

区块的上下外边距有时会合并&#xff08;折叠&#xff09;为单个边距&#xff0c;其大小为两个边距中的最大值&#xff08;或如果它们相等&#xff0c;则仅为其中一个&#xff09;&#xff0c;这种行为称为外边距折叠。注意&#xff1a;有设定浮动和绝对定位的元素不会发生外边…

ES6 Set数据结构

1.Set 是什么 Set是新的引用型的数据结构 它类似于数组&#xff0c;但是成员的值都是唯一的&#xff0c;没有重复的值。 Set本身是一个构造函数&#xff0c;用来生成 Set 数据结构。 Set函数可以接受一个数组作为参数&#xff0c;用来初始化。 2.Set特性&#xff08;重点概…

S4系统编辑屏幕报错 报错 RFC callback call rejected by whitelist

点击 Dialog 的布局 直接报错 经过检查&#xff0c;发现正式机和开发机在 SM59 TCP/IP链接 的 EU_SCRP_WN32不一样 把开发机的数据维护到生产机&#xff0c;就可以用了 RS_SCRP_GF_PROCESS_640RFC_GET_FUNCTION_INTERFACERS_SCRP_GF_PROCESS_640RS_SCRP_GF_RBUILDINFORS_SC…

Docker Volumes卷详解以及时区、时间同步技巧

文章目录 纠正网上的时区和时间同步的错误概念比较-v 和 --mount 标志来自外部 CSV 解析器的转义值-v 和 --mount 行为之间的差异 创建和管理卷启动具有卷的容器将卷与 Docker Compose 一起使用使用卷启动服务服务的语法差异使用容器填充卷使用只读卷 在计算机之间共享数据使用…

网络代理技术的广泛应用和安全保障

随着网络世界的日益发展&#xff0c;网络代理技术作为保障隐私和增强安全的重要工具&#xff0c;其在网络安全、爬虫开发和HTTP协议中的多面应用备受关注。下面我们来深入了解Socks5代理、IP代理以及它们的作用&#xff0c;探讨它们如何促进网络安全和数据获取。 Socks5代理和…

【SA8295P 源码分析 (四)】22 - QNX Ethernet MAC 驱动 之 emac_entry / emac_attach 函数源码分析

【SA8295P 源码分析】22 - QNX Ethernet MAC 驱动 之 emac_entry / emac_attach 函数源码分析 一、EMAC:libdevnp-emac-eth.so1.1 emac 启动初始化时机1.2 libdevnp-emac-eth.so 源码目录结构1.3 emac_entry() :libdevnp-emac-eth.so 库入口函数1.3.1 dev_attach 参数介绍1.3…

ES6 Iterator 和 for...of 循环

1.iterator 概念 ES6 添加了Map和Set。这样就有了四种数据集合&#xff0c;需要一种统一的接口机制来处理所有不同的数据结构。遍历器&#xff08;Iterator&#xff09;就是这样一种机制。它是一种接口&#xff0c;为各种不同的数据结构提供统一的访问机制。任何数据结构只要部…

Python 实现梯度下降算法总结

Python 实现梯度下降算法 最近重新回顾了一下机器学习的基础知识&#xff0c;关于梯度下降的知识&#xff0c;个人认为看懂原理和公式&#xff0c;仅仅是一方面&#xff0c;如果能从代码的角度重新实现或者走一遍可能会更加记忆深刻&#xff0c;下面两个参考链接讲的就非常好&a…

会议OA小程序【首页布局】

目录 一. Flex布局介绍 1.1 什么是Flex布局 1.2 基本概念 1.3 Flex属性 二. 会议OA首页轮播图的实现 配置 Mock工具 swiper 效果展示 三. 会议OA首页会议信息布局 index.js index.wxml index.wxss 首页整体效果展示 一. Flex布局介绍 布局的传统解决方案&#x…

【LeetCode】54. 螺旋矩阵

题目链接 注意边界 和 方向变化 文章目录 Python3方法一&#xff1a; 计算每个元素 下一个元素的下标 ⟮ O ( m n ) 、 O ( m n ) ⟯ \lgroup O(mn)、O(mn) \rgroup ⟮O(mn)、O(mn)⟯方法二&#xff1a;按层模拟 ⟮ O ( m n ) 、 O ( 1 ) ⟯ \lgroup O(mn)、O(1) \rgroup…