Git对象(objects)简介

Git对象(objects)简介

Git对象一共有三种:数据对象、树对象以及提交对象,这些对象都被保存在了.git/objects目录下, 下面我们将通过git命令来观察,分析这几个对象的产生过程,以期对Git版本控制系统的内部原理有个深入的理解。

数据对象(blob)

数据对象的产生是在使用git add命令将文件或者目录加入到暂存区时产生的,Git会把一个文件中要存储的数据和一个头部信息一起做SHA-1散列运算,将得到的散列值作为这个文件的路径,下面我们将通过具体过程来进行展示和分析。初始化一个Git仓库,将一个test.txt加入仓库暂存区
在这里插入图片描述
这时我们去objects目录下就会看到一个文件 12/651515fdbe068a7c5c74e3af3ba9be428d6f51
该文件名是由文件原内容加上特定头部信息一起做SHA-1散列值得到的,散列值前两字符用于命名子目录,余下的38个字符则用作文件名,这样我们就已经得到了一个Git下的数据对象
在这里插入图片描述
我们很好奇这个文件到底保存了什么东西,我们使用vim打开发现数据是被压缩的
在这里插入图片描述
我们可以通过cat-file命令来查看这个文件中的数据,为cat-file指定-p选项可以指示该命令自动判断内容的类型,并未我们显示格式友好的内容
在这里插入图片描述
显示的内容与加入暂存区之间文件中的内容是一样的,所以其实这个散列值路径文件中保存的只是源文件的一种压缩形式。
文件是这样加入到暂存区的,如果我用git add 将一个目录增加到暂存区会怎样:
在这里插入图片描述
经过上面的过程我们将一个有一个文件的目录加入到了暂存区,我们查看objects后发现仅仅只是多了一个新文件
在这里插入图片描述
使用cat-file 命令观察发现 该文件中没有任何关于目录test的信息,Git仅仅将里面的文件new.txt转化为Git中的一个数据对象。要解决Git如何存储目录信息这个问题我们就得了解树对象。
在这里插入图片描述

树对象(tree)

接下来我们探讨Git中的树对象, 它能解决文件名保存问题,也允许我们将多个文件组织到一起, Git以一种类似于UNIX系统的方式存储内容,但做了些许简化。所有内容均已树对象和数据对象的形式存储,其中树对象对应了UNIX中的目录项,数据对象大致对应了文件内容。现在我们通过git commit
命令来观察生成的树对象
我们将前面放在暂存区的文件进行commit
在这里插入图片描述
最后两行显示,Git为每一个文件设置了文件模式100644,表明这两个文件都是普通文件, 其他两种种模式选择包括:100755,表示一个可执行文件;120000,表示一个符号链接。上述三种模式即是Git数据对象的所有合法模式(当然对于目录项和子模块还有其他的一些模式)
提交之后我们再次观察objects目录内容:
在这里插入图片描述
我们可以看到这里面多了三个文件(为了方便起见我使用整个散列值的前6个字符来表示该文件)
分别是012d1f、1360eb和ee0b2b,在接下来树对象的讨论中我们主要分析012d1f和ee0b2b,而1360eb则属于提交对象的内容
我们使用cat-file -p读取ee0b2b文件, 这个文件中包含了一条树对象记录和一个数据对象记录,其中每条记录都指向一个数据对象或者是子树对象的SHA-1指针以及相应的模式、类型、文件名

第一条记录表示该树对象指向一个126551的数据对象,树对象的文件名为test.txt,模式为100644
第二条记录表示该树对象指向一个012d1f的树对象,树对象的名字为test,模式为040000(表示该文件名为一个目录)
在这里插入图片描述
然后我们读取 012d1f 树对象
在这里插入图片描述
该树对象包含一个指向698e7f的数据对象的指针,文件名为new.txt,模式为100644。
根据上面的分析我们弄清楚了目录问题:Git会将一个目录存储为一个树对象进行保存, 这个树对象中会有每个子目录的树对象条目和每个文件的数据对象条目,这样就可以根据一种树结构来保存整个目录。

提交对象(commit)

现在我们来分析1360eb文件,用cat-file读取:
在这里插入图片描述
我们会发现这个提交对象中包含一个树对象条目,代表着当前项目快照,从这树对象开始我们就能找到所有所有提交的数据对象,从而形成Git中的一个版本
其他之外还有一些作者/提交者的信息,留空一行,最后是提交注释。

总结

我们经历了完整的一次git提交过程,现在我们来思考一下git提供的这三种对象带来的高效率,首先git会对所有的文件内容进行压缩,这使得即使仓库中存储了非常多的内容,而.git也不会很大,然后就是速度,考虑这样的情况,当我们修改了一个文件的时候,git会去计算这个文件的SHA-1散列值,如果该散列值所得到的路径已经存在,那就说明,这个文件并没有被真正修改(或许是改了然后又改了回来。。。。),这不会带来任何字符串匹配问题,只是一个路径搜索过程,如果我们真正的修改了一个文件,那么git会计算这个文件的散列值,然后将这个文件压缩存储在objects中,这样我们需要创建一个相应的树结构来对原来的提交进行更改,这其实并不是一个困难的过程,我们只要为每一次提交都创建一个顶层树对象来表示这个提交快照。git可能会对比前一个提交的顶层树对象,然后将没有改变的树对象或数据对象直接复制到新创建的这个顶层树对象中,将改变的树对象像这样递归的进行。所以说决定你仓库大小的并不是完全在于每个文件的大小,而是你修改提交的次数,修改的次数越多,产生的树对象和数据对象也就越多。

### 回答1: "空目录不被支持: /.git/objects/info" 是一个错误信息,指出在 Git 版本控制系统中不支持空目录的创建。 在 Git 中,目录没有实质性的含义,仅用于组织文件和目录结构。Git 跟踪的是文件的更改,而不是目录的创建或删除。因此,如果仅创建一个空目录,Git 将无法将其跟踪或提交到版本控制中。 然而,Git 可以支持空目录的存在,但需要在目录中至少包含一个文件或子目录。这样,Git 就能够将该文件或子目录纳入版本控制,并随之跟踪该目录的存在。 如果你确实需要在 Git 仓库中创建一个目录,但又没有实际文件或子目录可放入其中,你可以通过在目录中创建一个空的 ".gitkeep" 文件来实现。该文件的名称可以是任意的,但通常使用 ".gitkeep" 是为了表明该文件的作用是保持目录的存在,使其能够被 Git 跟踪。 综上所述,"空目录不被支持: /.git/objects/info" 错误信息的意思是在 Git 中无法创建空目录,并提供了一种解决方法,即确保目录中至少包含一个文件或子目录来跟踪。 ### 回答2: "empty directories is not supported: /.git/objects/info"的意思是无法创建空目录:/.git/objects/info。 在Git版本管理系统中,每个存储库都有一个名为".git"的隐藏文件夹,该文件夹包含了版本控制所需的所有信息和数据。在这个隐藏文件夹中,有一个文件夹名为"objects",它用于存储存储库中的所有对象。 在这种情况下,系统不允许创建名为"/.git/objects/info"的空目录。这是因为Git维护存储库的内部结构,并需要确保所有的目录和对象都是有效的和有用的。 如果你尝试创建空目录"/.git/objects/info",系统会拒绝这个请求,因为它会破坏Git存储库的结构,并可能导致一些错误或数据丢失。 所以,如果你需要在Git中存储一些特定信息,建议你使用其他有效的方法,例如使用分支、标签、提交信息或Git属性等。这些方法可以帮助你在不破坏存储库结构的情况下,有效地组织和管理你的工作。 ### 回答3: 空目录不被支持的意思是指在.git/objects/info目录下是不能存在空目录的。在Git中,.git文件夹是存储版本控制数据的核心文件夹,包含了所有的版本历史、对象和配置信息等等。 在Git中,对象Git存储的最基本的数据单位,包括提交(commit)、(tree)和blob等。.git/objects/info文件夹下存储了一些附加的对象信息。然而,Git不允许这些对象信息的文件夹下存在空目录,这是为了保持版本库的结构的一致性和简洁性。 当我们在.git/objects/info下创建空目录时,Git会发出上述错误信息。这是因为Git会在对象文件夹中自动清理空目录,以确保版本库不会包含无用的目录。空目录可能会导致版本库结构混乱,增加处理难度。 要解决这个问题,可以通过在.git/objects/info下创建一个不为空的文件,例如可以创建一个空的README文件。这样就不会有空目录存在了。或者,可以将该空目录删除,以保持版本库的结构简洁和一致。 总之,空目录不被支持的原因是为了保证版本库的结构简洁性和一致性。在.git/objects/info目录下不应该存在空目录,需要注意这一点,以避免产生不必要的错误提示。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值