【Git教程】(四)版本库 —— 存储系统


对象数据库是一个非常高效的实现。即使对于一个有着非常长提交历史的大型项目(例如Linux内核,这是一个拥有 200000次提交和近两百万个对象的项目)来说,访问其版本库 中对象的操作也几乎可在瞬间完成。Git 非常适合用于那些拥有大量小型源文件的项目。其性能瓶颈只有在总数据量非常巨大的时候才能显现出来。对于那些想要管理大量二进制文件的人来说,Git 版本库显然是不二的选择。


  

## 2️⃣ 存储目录:Blob 与 Tree


在文件和目录的存储上,Git 使用了一种包含两种节点类型的简单树结构。其文件内容将 保持不变,并以blob 对象的形式按字节被存储对象数据库中。而目录则将用tree 对象来表示, 它们看起来应该像如图所示。


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/aded008befed4c7bb458a0864d92d3f5.png#pic_center)



git cat-file -p 2790ef78
100644 blob 507d3a30ae9ed53bcf953744c5f5c9391a263356 README
040000 tree 91c7822ab43800b0e3c13049519587df4fd74591 src


正如你将如上看到的, tree 对象中包含了文件和子目录。其中的每个条目都被分配了 相应的访问权限(例如上面的100644)、类型(即 blob 还是 tree), 以及由该文件内容、该文  
 件或目录名称生成的散列值。


  

## 3️⃣ 相同数据只存储一次


为了节省内存空间, Git 对于相同数据将只存储 一 次。例如在下面这个例子中,`foo.txt` 和 `copy-of-foo.txt` 将返回相同的散列值,因为它们的文件内容是相同的。



git hash-object -w foo.txt
a42a0aba404c21le8fdf33d4edde67bb474368a7
git hash-object -w copy-of-foo.txt
a42a0aba404c21le8fdf33d4edde67bb474368a7


通过这种方法, Git 不仅能够节省内存,同时也能在性能上得到提升。许多Git 操作之所以快,就是因为它们的算法只比较相关的散列值,而不需要查看其实际数据。


  

## 4️⃣ 压缩相似内容


Git 不仅可以对相同的文件内容进行合并,每当程序员们所创建的新文件在内容上与前人 只有区区几行的区别时,Git 可以采用增量方法来存储这些文件,在这种情况下,包文件中将只存储原始版本后来被改变的那一部分。


要想做到这一点,我们就要在想节省空间时使用 `gc` 命令。这样一来,Git 就会删除所有多余的、不再接受任何分支头访问的提交,并将剩下的提交存储到包文件中。对于那些源代码占绝大多数的项目来说,这就等于实现了某种令人惊叹的高压缩处理。通常情况下,当前版本未压缩的工作区内容大小往往要比包含多年项目历史并打包的Git 版本库还要大得多。


  

## 5️⃣ 不同文件的散列值相同


当不同文件的散列值相同时,情况会很糟糕,因为 Git 是通过散列值来识别内容的。因此, 一 旦内容各不相同的文件出现散列值相同的情况,Git 就无法提供正确的数据了,我们称这种情况为敬列冲突(hash collision)。


好消息是,敬列冲突是一种非常罕见的事件。其原因在于,散列值的可能取值至少有2160 种。而即使是Linux 内核项目在运作5年之后,版本库中也就“仅有”大约221个对象。


当然从理论上而言,SHA1 敬列算法是有缺陷的,你可以在 SHA1 算法中找到251 中会 引起敬列冲突的操作。然而,格拉茨科技大学 (Graz University of Technology) 的一个研究项目曾从2007年尝试到2009年,目的是想找出一个(!) 这样的散列冲突,结果以失败告终。


总而言之,在当今版本控制所在的环境下,我们可以认为它是安全的。  
   



## 6️⃣ 提交对象


我们所做的历次提交也被存储在对象数据库中,它们的格式很简单。



git cat-file -p 64b98df0
tree 319c67d41a0b3f7464550b41db4bb1584939ad2a
parent 6c7f1ba0828a5b595026e08d2476808105a6b815
author Bjorn Stachmann bs@test123.de1295906997 +0100
committer Bjorn Stachmann bs@test123.de1295906997 +0100
Section on trees & blobs.


除了作者、提交者、日期以及注释这些元数据外,每个提交对象还在对象数据库中放入 了一些其他对象的散列值。例如: `tree` 对象负责描述该提交的内容。它还包含了该项目的根目录信息,并且与上文提到的一样,它也将以tree 和 blob 对象的方式呈现。而 `parent` 对象则指的是它的上一次提交。


  

## 7️⃣ 提交历史中的对象重用


除了最初的那次提交外,版本库中的每个提交对象上面都至少会存在一个前提交对象(即 父对象)。通常来说, 一次提交往往只涉及项目中少数文件的修改,其他大部分文件和目录不会发生变化。所以,我们会希望 Git 尽可能多地重用前次提交中的相关对象。


下面我们来看一个具体的例子(见下图)。某一提交(即自顶向下第二排中第二个被 实线箭头所指向的那个标题为 “commit” 的方框)中包含了一个README 文件,以及一个 用于包含其他文件的 src 目录。然后,如果在新建的提交(即图中第一行用虚线箭头所指向 的那个标题为 “commit” 的方框)中,被修改的只有 README 文件, Git 就会专门为该 README 文件创建一个新的blob对象。而对于src 目录,则继续沿用现有的tree对象与相应的 blob 对象。


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/c9113acb314345ee97cc9cbf0dfdfe49.png#pic_center)


  

## 8️⃣ 重命名、移动与复制


在许多版本控制系统中,我们都可以对文件的重命名及其修改时间的历史进行跟踪监视。  
 它们大多数通常是通过某个特定的文件移动或重命名命令来实现的。例如在 Subversion 中,我们可以用 svn move 来移动文件。但是如果用户想要将文件在图形界面中拖放到某一新的位置的话, Subversion 就无能为力了。对于这种情况, Subversion 不会认为这是个移动操作,而会将其记录为先删除,再另行新建该文件的操作过程。


对此,Git 采用了不同的方法:它没有选择去存储与文件移动操作相关的信息,而是采用 了重命名检测算法。在该算法中,如果一个文件在某一次提交中消失了,它依然会存在于其 前次提交中。而如果某个拥有相同名字或相似内容的文件出现在了另一个位置, Git 就会自动检测到。如果是这种情况, Git 就会假定该文件被移动过了。下面我们以下图中的情况为例 来演示一下。你可以看到:第二次提交中已经没有了 foo.txt 文件,它可能被移动了。随后,Git 又自动检测到新增文件中有一个与之内容相似的文件,位于src/foo-moved.txt, 这一过程就成为了重命名操作。


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/40f331fddd6a4e509051971b0729bc7c.png#pic_center)Git 会自行显示出被重命名或移动的文件。


1. 先获取一份摘要  
 我们可以用 log 命令的-M 选项 ( 即“move”) 来激活重命名的检测算法。如果想要格式化输出的信息,我们可以对其使用–summary 选项来显示文件修改的相关信息。但这段输 出很长也是个问题。如果我们想要简短一些,也可以用grep命令来对输出进行筛选。另外,百分比显示了源文件和目标文件的相似度。

 

git log --summary -M90% | grep -e “^ rename”
rename foo.txt => foo-renamed.txt(90%)
rename src/{before =>after}/bar.txt(100%)

2. 跟踪被移动文件的历史  
 我们可以用 log 命令的–follow 选项来连续取出文件被重命名之后的历史记录(当然,该做法仅适用于单文件操作)。如果不使用该选项,日志就会在该文件被重命名的那一刻停止。

 

git log --follow foo-renamed.txt



我们还可以透过-C 选项来跟踪被复制的数据。



git log --summary -C90% | grep -e “^copy”


如果有必要的话,我们也可以用 `--find-copies-harder`选项来使Git 做一个更长的计算操作。只要该选项被激活,Git 就会去检查相关提交中的所有文件,并不仅仅是那些已更改的文件。


我们也可以将重命名检测配制成 Git 的默认选项。这样一来,我们就无需在每次使用 log  
 命令时为其指定`-M` 和`--follow` 选项了。



git config diff.renames true


我们可以按照以下步骤找出谁最后修改了那几行代码,以及修改的时间。


1. 逐行打印源头信息  
 当我们将某些较大的代码块复制或移动到其他文件中时,Git 甚至可以确定其中某几行 代码的来源。而且, blame 命令还可以显示出最后一次修改这几行代码的人及其修改时间。

 

git blame -M -C -C -C copied-together.txt
f5fdbad0 foo.txt (Rene 2010-11-1418:30:42 +0100 1)One
a5b80903 bar.txt (Bjorn 2011-01-3121:32:49 +0100 2)Two or
f5fdbad0 foo.txt (Rene 2010-11-1418:30:42 +0100 3)Three



其中的 -M 选项(M 代表“move”) 暗示的是文件的复制和移动操作。 -C 选项也可用于 检测相同提交中的文件副本。但我们还可以用多个-C 选项来搜索该文件在更多提交中的副本。对于大型的版本库来说,这种操作有时候会需要较长的时间。  
   



## 🌾 总结


* 对象数据库:所有提交中的文件、目录以及相关的元数据都将被存储在该数据库中。
* SHA1 散列值:我们可以通过一个SHA1 散列值从对象数据库中捡取相关对象。SHA1 散列值是一种针对文件内容的加密校验值。
* 相同数据只存储一次:内容相同的对象拥有相同的 SHA1 散列值,并且只存储一次。
* 相似的数据会被压缩:对于内容相似的数据, Git 会针对其被修改的部分采取增量存储的方法。
* Blob对象:文件的内容将会被存储在相应的blob对象中。
* Tree 对象:目录会被存储在相应的 tree对象中。 一个 tree 对象中通常会包含一份文件 名列表,包含这些文件名和储存在blob 或 tree 对象中内容的 SHA1 散列值。
* 提交图:我们的提交对象会沿着各自的 tree 和 blob对象,形成一个提交图。


**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/4fe7ebc5a5c5749e530d165c053ba4a5.png)
![img](https://img-blog.csdnimg.cn/img_convert/597be0411ac3932319ee81dece0cd2e3.png)
![img](https://img-blog.csdnimg.cn/img_convert/e07f4ed8708cbf60bb0f981ec5503957.png)
![img](https://img-blog.csdnimg.cn/img_convert/eb11595692866afedf8a62d85b183aa1.png)
![img](https://img-blog.csdnimg.cn/img_convert/aa90c4ae198806d66ba9c4f3aaa861f5.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)**
![img](https://img-blog.csdnimg.cn/img_convert/3dcf877d7eca9dc1e13a67ff65750aa6.png)

有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)**
[外链图片转存中...(img-WedsSbnP-1712868245218)]

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值