一些Git内部构件

2020-12-26 04:14:15

(这是我于2015年9月27日首次发布的更新/修订的博客文章。)这是我的测试文件树。有两个文件和一个" src"子目录,其中存储了另外两个文件:

现在,我将所有这四个文件添加到git repo中并进行初始提交。在.git子目录中创建了许多文件。让我们首先关注对象。目录。这些文件:

众所周知,所有这些文件都是使用Zlib压缩器压缩的。还有" zpipe"可以帮助解压缩Zlib压缩文件的util(至少在Ubuntu的opencaster软件包中提供,源代码)。

dennis @ wombat:〜/ tmp / test / .git $ zpipe -d< objects / 4a / cde9ab6dd9bf439ff2cbddb47d5e96b1f2e3adblob 54 //这是" hello world"的源代码程序

哇,这是我们熟悉的。但是压缩文件的前面是" blob 54"字符串。" blob"表示此对象具有" blob"类型,即包含文件。" 54"的长度是" blob"的内部还有一个零字节,使用hexdump可以看到:

dennis @ wombat:〜/ tmp / test / .git $ zpipe -d< objects / 4a / cde9ab6dd9bf439ff2cbddb47d5e96b1f2e3ad | hexdump -C00000000 62 6c 6f 62 20 35 34 00 2f 2f 20 74 68 69 73 20 | blob 54.//此| 00000010 69 73 20 73 6f 75 72 63 65 20 63 6f 64 65 20 66 |是源代码f | 00000020 6f 72 20 74 68 65 20 22 68 65 6c 6c 6f 20 77 6f |或hello wo | 00000030 72 6c 64 22 20 70 72 6f 67 72 61 6d 0a 0a | rld"程序.. | 0000003e

我们可能已经听说git中的对象ID是其内容的SHA1。确实是这样。但是内容的前面是一个由对象类型和对象大小(我们刚刚看到的)组成的字符串,我们可以检查这是否成立:

的确如此。但是SHA1 sum的第一个字节是子目录,其余所有都是压缩对象的文件名。还有其他计算git SHA1 sum的方法:http://stackoverflow.com/questions/552659/assigning-git-sha1s-without- git。

dennis @ wombat:〜/ tmp / test / .git $ zpipe -d<对象/ 2e / c39aec17a9e53d21dcdafd8cdbe3ae7ada8c57 | hexdump -C00000000 74 72 65 65 20 37 30 00 31 30 30 36 34 34 20 68 |树70.100644 h | 00000010 65 6c 6c 6f 2e 63 00 4a cd e9 ab 6d d9 bf 43 9f | ello.cJ..m。 C. | 00000020 f2 cb dd b4 7d 5e 96 b1 f2 e3 ad 31 30 30 36 34 | ....} ^ ..... 10064 | 00000030 34 20 77 6f 72 6c 64 2e 63 00 61 d7 f2 fc b4 d4 | 4 world.ca .... | 00000040 aa 0c 55 ab b0 7f 0c ca 6f d6 ff a9 1e 00 | ..U ..... o ..... | 0000004e

现在,这是最有趣的部分:该对象具有压缩后的< tree"换句话说,这只是目录中的文件列表。用肉眼可以看到" tree"对象。对象类型开头,然后是" 70" (对象大小),然后具有" hello.c"的访问权限文件,然后访问" world.c"的访问权限file。两个文件名都清晰可见。

这两个哈希是存储文件的对象的ID。您可以在十六进制转储中找到这些ID,它们以二进制形式存储在其中,以使事情更快,更紧凑。有趣的是:" tree"的压缩对象“类型”在树中登记降序对象,但未指定其类型,因为可以轻松地从对象本身推断出它们的类型。

所以这棵树的文件列表为" src"子目录。也没有文件/目录时间戳,因为git不会保留它们。

dennis @ wombat:〜/ tmp / test / .git $ zpipe -d<对象/ ef / 875aac086693ff89d2a21dbe2a78c34f053a73 | hexdump -C00000000 74 72 65 65 20 31 30 37 00 31 30 30 36 34 34 20 |树107.100644 | 00000010 69 6e 73 74 61 6c 6c 2e 74 78 74 00 d7 a7 d9 d0 | install.txt ..... | 00000020 4d 26 cf bf e4 a4 92 a7 37 f4 f8 1d 99 3d bc e6 | M& ...... 7 .... ==。| 00000030 31 30 30 36 34 34 34 20 72 65 61 64 6d 65 2e 74 78 | 100644 readme.tx | 00000040 74 00 8b 35 c7 d4 62 2c 1a a1 15 31 16 6e 4b d7 | t..5..b,... 1.nK. | 00000050 d1 90 1c 9d 5d 2b 34 30 30 30 30 20 73 72 63 00 | ....] + 40000 src。| 00000060 2e c3 9a ec 17 a9 e5 3d 21 dc da fd 8c db e3 ae | ....... =!... .... | 00000070 7a da 8c 57 | z..W | 00000074

它包含根目录的文件列表:两个文件" install.txt"和" readme.txt"以及" src"子目录。让我们使用git实用程序将其转储:

文件ID是存储其内容的对象的ID。ID为" src" 树只是另一棵树的ID。 对象,该对象之前已检查过。 dennis @ wombat:〜/ tmp / test / .git $ zpipe -d< objects / 25 / 457e6ce216a231dc45ad1f08449c72d2a3a674commit 189tree ef875aac086693ff89d2a21dbe2a78c34f053a73作者Dennis Yurichev 1442582288 + 0300committer Dennis Yurichev 1442582288 +0300最初提交 这是表示" commit"的对象。 它具有一棵树的ID以及一些其他信息,包括提交的日期/时间,我们可以确定这是当前HEAD指向的位置: 25457e6ce216a231dc45ad1f08449c72d2a3a674是具有" commit"的对象的ID。 我们刚刚看到的信息。