Git包文件

Git通过保存文件快照来管理版本,即使小改动也会完整存储。然而,通过包文件(packfile)机制,Git能高效存储,减少空间占用。当对象数量达到一定阈值或执行`git gc`时,Git会将松散对象打包,利用差异存储,优化存储空间。文章通过实例展示了Git对象从松散到打包的过程,解释了Git如何节省存储并提高效率。
摘要由CSDN通过智能技术生成

Git保存的是文件的快照,即:会保存每个文件的每个版本的完整内容,若是一个文件只做了一个小小的改动,比如只修改了一个字符,那岂不是除了这个字符的其他内容全部存了两遍?那能否让Git只完整的保存其中一个,另一个以版本差异的方式保存呢?其实,Git是可以做到的,Git最初向磁盘中存储对象时所使用的格式被称为“松散(loose)”对象格式,但是,Git还使用了一种更效的存储机制,被称为“包文件(packfile)”的二进制文件,以节省空间和提高效率。

首先,我们准备一个较大的文件repo.rb(22k),并将其添加到版本库:

$ git add repo.rb
warning: LF will be replaced by CRLF in repo.rb.
The file will have its original line endings in your working directory

$ git commit -m "added repo.rb"
[master a6a3d60] added repo.rb
 1 file changed, 709 insertions(+)
 create mode 100644 repo.rb

$ git cat-file -p master^{tree}
100644 blob e212b11d921e98c6444eb6c946de48ca39da9131    new.txt
100644 blob 033b4468fa6b2a9547a70d88d1bbe8bf3f9ed0d5    repo.rb
040000 tree 1e18318519c5897cbbe86691f3c484c825b776e5    sub
100644 blob 3093e3da8ea43704f4768d791376eda3c056c6ef    test.txt

$ git cat-file -s 033b4468fa6b2a9547a70d88d1bbe8bf3f9ed0d5
22044

此时生成的数据对象为033b4468,然后,对文件repo.rb进行修改并提交:

$ echo '# testing' >> repo.rb

$ git commit -am "modify repo a bit"
warning: LF will be replaced by CRLF in repo.rb.
The file will have its original line endings in your working directory
[master ffca670] modify repo a bit
 1 file changed, 1 insertion(+)

$ git cat-file -p master^{tree}
100644 blob e212b11d921e98c6444eb6c946de48ca39da9131    new.txt
100644 blob b042a60ef7dff760008df33cee372b945b6e884e    repo.rb
040000 tree 1e18318519c5897cbbe86691f3c484c825b776e5    sub
100644 blob 3093e3da8ea43704f4768d791376eda3c056c6ef    test.txt

$ git cat-file -s b042a60ef7dff760008df33cee372b945b6e884e
22054

此时新生成的数据对象为b042a60e,并且文件的大小由22044变成了22054。当我们向远程服务器执行推送时,或者手动执行git gc命令时,Git都会将松散的对象打成包文件:

$ git gc
Enumerating objects: 19, done.
Counting objects: 100% (19/19), done.
Delta compression using up to 8 threads
Compressing objects: 100% (12/12), done.
Writing objects: 100% (19/19), done.
Total 19 (delta 1), reused 0 (delta 0), pack-reused 0

这个时候再查看 objects 目录,我们会发现大部分的对象都不见了,与此同时在.git/objects/pack目录下面出现了一对新文件:

$ find .git/objects/ -type f
.git/objects/info/commit-graph
.git/objects/info/packs
.git/objects/pack/pack-b0bc3e789c301ef29e409784de730539be4d9481.idx
.git/objects/pack/pack-b0bc3e789c301ef29e409784de730539be4d9481.pack

可以通过git verify-pack命令查看已打包的内容:

$ git verify-pack -v .git/objects/pack/pack-b0bc3e789c301ef29e409784de730539be4d9481.idx
ffca6702b866e0ea55b5814978c5bddc74341b0d commit 224 152 12
a6a3d60b6b016c4004668e3f4631238227ca4a3b commit 220 148 164
adce7c0d7c4ebe520a5015d99a0cc6c04cb86312 commit 219 148 312
0bcaf18821af42d243343a6cbb6042faf3d9ff22 commit 220 150 460
acda5662c5b9d21a9b35a44e71d7ba3adfe6bcf6 tag    141 129 610
6696fbe9f7c1cd84b1404c1c784c36ab0af7cd50 commit 171 120 739
12df1c8e96c426882aa65af9fc703b1e7aa1c3df tree   136 137 859
1e18318519c5897cbbe86691f3c484c825b776e5 tree   39 50 996
9d1957e6a0fd284aa17a9824ccea897d045b5a7b tree   136 137 1046
ec6ef32dc11b034bd34d2a05becfc9738debe59a tree   101 106 1183
4af7fccde05f38392e4f6d43f5b92e356b0301dc tree   71 76 1289
30eb43eb353c7fc2352f8e57ea0ebecb5fbbc468 tree   36 47 1365
e212b11d921e98c6444eb6c946de48ca39da9131 blob   16 26 1412
b042a60ef7dff760008df33cee372b945b6e884e blob   22054 5799 1438
033b4468fa6b2a9547a70d88d1bbe8bf3f9ed0d5 blob   9 20 7237 1 b042a60ef7dff760008df33cee372b945b6e884e
387bf721cf870334f40cb87829a818f9fa421285 blob   14 23 7257
3093e3da8ea43704f4768d791376eda3c056c6ef blob   10 19 7280
786ae1f3a311f95e95ce47702dcfd9e9ed2cb27b blob   14 23 7299
dffc3d5ed8d6a2f7982ff91e720d3c0baca0d6db blob   10 19 7322
non delta: 18 objects
chain length = 1: 1 object
.git/objects/pack/pack-b0bc3e789c301ef29e409784de730539be4d9481.pack: ok

此处,033b4468这个数据对象是repo.rb文件的第一个版本,它引用了数据对象b042a60e,即repo.rb的第二个版本,第三列显示的是对象的大小,数据对象b042a60e占用了22k,而数据对象033b4468仅占用了9字节,并且,是repo.rb的第二个版本保存了完整的内容,而第一个版本是以差异方式保存的,这是因为绝大多数情况下,需要快速访问文件的最新版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值