看看.git文件夹

您一生中最大的恐惧是什么? 对我来说,想到在.git文件夹中住一晚。

恶作剧吧? 是的,我知道。 但是传统上.git被认为是一个可怕的地方,具有可怕的数据结构,肮脏的二进制文件等。 让我们尝试看看这些故事中有多少真相。 让我首先揭穿git将数据存储为补丁的城市传说。 Git不会存储信息或将其提交为patch / diff / hunk文件。

整个git repo历史记录都表示为图形数据结构,其中每个提交都是图形的节点。 在任何时候,git commit或节点都指向该存储库的整个快照。 在进一步介绍之前,先举一个例子

  $ mkdir git-demo 
$ cd git-demo
$ git init
$ echo“ kochi pazhaya kochiyalla..pakshe Bilal”> file1.txt
$ git添加file1.txt
$ git commit -m“第一次提交”

每当将新文件添加到git时,git都会找到文件的sha1-hash并将其以压缩格式保存在以下位置

.git/objects/first-2-characters-of-hash/remaining-characters-of-hash

我们的例子看起来像

现在让我们看看该文件的内容,

git cat-file -p thefullhashgit cat-file -p first_few_chars_of_hash

当您执行git commit时,git实际上会返回该提交的哈希,它实际上是文件的哈希(其内容是指向该文件的指针(又是一个哈希),该文件具有仓库中所有文件的列表)以及一些元数据,例如作者,时间等。

WTF。 是的,让我们尝试将其分解,

提交是FILE的哈希。 该FILE的内容是指向TREE和一些元数据的指针。 此树是哈希列表。

所以让我们看看这个提交56ace24

git cat-file -p 56ace24

请记住,上图显示的内容是objects/56/ace24……二进制/压缩文件的内容objects/56/ace24……

好。 我们的提交包含有关提交本身的元数据和指向树45a3a..的指针,该指针再次出现在objects/45/a3ae3…

  $ git cat-file -p 45a3ae3c5016e4e6499264924e66c8b0da094c50 
100644 blob ac1ce5f2d53592130643ce18e4c62b042aa2a973 file1.txt

在某些git版本中,您可能必须使用git ls-tree 45a3ae3命令才能看到上面的正确输出。 因此,我们的树只是该提交中的文件列表,以及指向git文件系统中确切文件/ blob的指针。 现在,当我执行git cat-file ,我将在blob中获得确切的内容。 因此,树是仓库中任何点的仓库快照。 因此,现在我们确定git存储了仓库的确切快照,而不是补丁,而不是diff文件。

现在我要在我们的仓库中添加一个文件

  $ echo“ chetta kurachu choridatte”> file2.txt 
$ git添加file2.txt
$ git commit -m“ Choru提交”
[master f862298] Choru提交
更改1个文件,插入1个(+)
创建模式100644 file2.txt

重复相同的过程以跟踪提交,

因此,现在我的提交文件或哈希具有更多信息,称为提交的父项。 现在,这很清楚了,当您执行git checkout HEAD~3时,git如何显示日志或进行检出。 Git只需要在图中追踪即可。 当您要求git签出到特定提交的工作存储库或转到Current-N提交时,git需要遍历该图以查找正确的提交文件,只需将当前存储库替换为树文件中的所有文件快照即可。 这正是git超快速的原因。 想象一下,您想回到HEAD~100提交,如果git存储了所有补丁文件,假设每次提交更改2个文件,那么git需要应用1000个补丁才能达到这一点,而事实并非如此。智能git实现。

您可能已经知道的几件事,

  1. 如果两个文件的内容完全相同,那么git只会将它们存储一次,这很明显,因为哈希值是相同的。 因此,连续提交之间未更改的文件将不会创建额外的副本。 所以git并不是那么昂贵😀
  2. 合并提交将有两个父级。 是的,这是一个图形数据结构。
  3. 文件中的单个字符更改将导致git在文件系统中创建一个新的blob。 这就是经常被告知不要对大型文件使用git的确切原因。 对于大型文件,Git在成本和性能方面将变得非常昂贵。 存在诸如git-bigfiles之类的项目作为使用git处理较大文件的解决方案。

HEADbranch都是指向图中节点的指针。

只需尝试一个小型git项目并仔细查看对象,即可使事情变得清晰。

SHA-1安全吗?

自从那天以来,很少有google工程师成功地证明了sha-1漏洞,因此关于git使用sha-1进行计算的争论不断。 Linus消除了这篇文章中的所有担忧,因为git并未使用SHA算法进行任何安全性验证,而只是查看文件是否已更改而不会构成任何严重的威胁,因此很明确。 他还接受这样一个事实,即可以将诸如pdf (使用漏洞利用程序创建)之类的二进制文件实际上添加到存储库中,以弄乱事情,但是它们是非常糟糕的情况。

另请阅读有关有人尝试测试SHA-1冲突时Webkit存储库崩溃的信息。 大声笑。 在这种情况下,错误是与Apache SVN有关的。

我的google pdf测试失败

由于这两个具有不同内容的pdf给出相同的sha-1哈希值,因此我期望将这些pdf添加到git repo会出错。

我的树文件实际上给了我两个Blob条目,因为两个文件都给我相同的哈希值,所以我只希望有一个Blob条目。 在一个关于git如何计算sha-1散列的google搜索中,我偶然发现了stackoverflow上的这篇文章。 因此git不会直接计算哈希值,而是会在对哈希值进行哈希处理之前将长度和字符串blob到内容中,这证实了我的测试失败的原因。 顺便说一句,在不同音符上,相同字符加到相冲突的pdf不会给您相同的哈希值

免责声明

感谢Edward Thomson在GOTO会议上的演讲。 是的,这篇帖子是他的视频😀的无耻抄录。 感谢Akash分享视频。