原文: http://gitbook.liuhui998.com/7_5.html

一、打包文件索引
首先, 我们来看一下打包文件索引, 基本上它只是一系列指向打包文件内位置的书签.
打包文件索引有两个版本.
 版本1的格式用于Git 1.6版本之前, 版本2的格式用于Git 1.6及以后的版本. 
但是版本2可以被Git 1.5.2及以上的Git读取, 同时也被后向移植(backport)到了1.4.4.5版本.
版本2包含了每个对象的CRC校验值, 因此在重打包的过程中, 压缩过的对象可以直接进行包间拷贝(from pack to pack)而不用担心数据损坏. 版本2的打包文件索引同时亦支持大于4G的打包文件.
在两个版本格式中, sha1表存储的是对象的SHA1值,并把它们按照其SHA1值进行排序(以便于对这个表进行二分搜索),  offset表存储的是sha1表中对应位置的对象在打包文件中的偏移值。
为了加速对象的查找,git使用了分段的思想,在打包文件中包含了一个fanout表。fanout表用一种特殊的方法指向offset/sha1表。
简单的说应该是这样的,fanout[0]表示的是SHA1值以0x00开头的所有的对象中SHA1值最小的对象在offset/sha1表中的偏移;fanout[1]表示的是SHA1值以0x01开头的所有的对象中SHA1值最小的对象在offset/sha1表中的偏移;fanout[2]表示的是SHA1值以0x02开头的所有的对象中SHA1值最小的对象在offset/sha1表中的偏移。以此类推,fanout[254]表示的是SHA1值以0xfe开头的所有的对象中SHA1值最小的对象在offset/sha1表中的偏移,fanout[255]表示的是SHA1值以0xff开头的所有的对象中SHA1值最大的对象在offset/sha1表中的偏移,它同时也表示了当前offset/sha1表的大小。
因此通过SHA1值查找一个对象时,首先通过SHA1值的前两位在fanout表中,确定它在offset/sha1表的一个区间范围,然后再在sha1表中根据SHA1值使用二分法进行查找。这样通过fanout表对于最坏的情况就减少了8次二分搜索迭代。
 
在第1版中, offset(偏移)和SHA值存在在同一位置. 但是在第2版中, SHA值, CRC值和offset被放在不同的表中. 两个版本的文件最后都是索引文件以及指向的打包文件的CRC校验值.
 
很重要的一点是, 要从打包文件中提取(extract)出一个对象, 索引文件不是必不可少的. 索引文件的作用是帮助用户快速地从打包文件中提取对象. 那些"上传打包"(upload-pack)和"取回打包"(receive-pack)程序(译注: 实现push和fetch协议的程序)使用打包文件格式(packfile format)去传输对象, 但是没有使用索引 .因为 索引可以在上传或者取回打包文件之后通过扫描打包文件重新建立.
二、打包文件格式
打包文件格式是很简单的. 它有一个头部(header)和一系列打包过的对象(每个都有自己的header和body), 还有一个校验尾部(trailer). 前4个字节是字符串'PACK', 它用于确保你找到了打包文件的起始位置. 紧接着是4个字节的打包文件版本号, 之后的4个字节指出了此文件中入口(entry)的个数. 你可以用下面Ruby程序读出打包文件的头部:
def read_pack_header
  sig = @session.recv(4)
  ver = @session.recv(4).unpack("N")[0]
  entries = @session.recv(4).unpack("N")[0]
  [sig, ver, entries]
end
头部之后是一系列按照SHA值排序的打包对象, 每一个打包对象包含了头部和内容. 打包文件的尾部是该文件中所有(已排序)SHA值的SHA1校验值(20字节长)(译注: 即按照排序好的顺序进行迭代SHA1运算).

对象头部(object header)由1个或以上的字节按序组成, 它指出了后面所跟数据的类型及展开后的尺寸. 头部的每一个字节有7位用于数据, 第1位用于说明头部是否还有后续字节. 如果第1位是'1', 你需要再读入1个字节(译注: 即下一字节仍属于头部), 否则下一字节就是数据. 第一个字节的前3位指定了数据的类型, 具体含义参见下表.

 
(3个位可以组合成为8个数. 在当前的使用中, 0(000)是'未定义', 5(101)目前未被使用.)
 
这里我们举一个由两个字节组成的头部的例子. 第1个字节的前3位说明了数据的类型是提交(commit), 余下的4位和第2个字节的7位组成的数字是144, 说明数据展开后的长度是144字节.
 
值得注意的一点是, 对象头部中包含的'尺寸'不是后面跟着的数据的长度, 而是数据展开之后的长度. 因此, 打包索引文件中的偏移是很有用的, 有了它你不必展开每一个对象就可以得到下一个头部的起始位置.
对于非delta对象, 数据部分就只是zlib压缩后的数据流. 对于那两种delta对象, 数据部分包含了它所依赖的基对象(base object)以及用于重构对象的delta(差异)数据. 数据的前20个字节称为ref-delta, 它是基对象SHA值的前20个字节. ofs-delta存储了基对象在同一打包文件中的偏移. 任何情况下, 有两个约束必须严格遵守:
1、delta对象和基对象必须位于同一打包文件;
2、delta对象和基对象的类型必须一致(即tree对tree, blob对blob, 等等).

Git打包文件的更多相关文章

  1. dotnet pack 打包文件版本号引起 "Could not load file or assembly" 问题

    如果不是遇到,真的不会想到,代码世界的问题真是千奇百怪,这次遇到的是 dotnet pack 打包文件版本号引起的问题. 之前进行 nuget 打包都是在 Visual Studio build 时进 ...

  2. gulp批量打包文件并提取公共文件

    gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器. browseriyf是模块化打包工具. 一般情况下,Browserify 会把所有的模块打包成单个文件.单个文件在大多数情况下是 ...

  3. java打包文件夹为zip文件

    //待压缩的文件目录 String sourceFile=sourceFilePath+"\\"+userName; //存放压缩文件的目录 String zipFilePath ...

  4. Wix 安装部署(一)同MSBuild 自动生成打包文件

    因为项目需要,最近在研究Wix打包部署,园子里也有一些关于wix的博客,方方面面,讲的点各不同.我自己也在测试过程中,写下过程,以供参考.最新版本WiX Toolset v3.7,如何安装的就不说了, ...

  5. JAVA代码实现下载单个文件,和下载打包文件

    //下载单个文件调用方法 /**     * response     * imgPath 下载图片地址    * fileName 保存下载文件名称    * @date 2015年4月14日 下午 ...

  6. java jar包解析:打包文件,引入文件

    java jar包解析:打包文件,引入文件 cmd下: jar命令:package包打包 javac命令:普通类文件打包 Hello.java: package org.lxh.demo; publi ...

  7. git 添加文件

    git 添加文件三步骤 git add filename git commit -m 'remarks' git push origin master

  8. 请问用Inno_Setup打包文件夹时怎么排除其中一个文件?

    请问用Inno_Setup打包文件夹时怎么排除其中一个文件? 该文件夹下有几十个文件,多个文件夹,我要一个个加进去该累死,也容易出问题.不知道能不能实现我要的目的. http://www.jrsoft ...

  9. Git忽略文件方法【转】

    转自:http://www.cnblogs.com/shangdawei/archive/2012/09/08/2676669.html http://cwind.iteye.com/blog/166 ...

随机推荐

  1. Camera

    Unity摄像机Viewport使用   http://blog.sina.com.cn/s/blog_64ab3f630100y7e7.html http://blog.sina.com.cn/s/ ...

  2. python 基本数据类型分析

    在python中,一切都是对象!对象由类创建而来,对象所拥有的功能都来自于类.在本节中,我们了解一下python基本数据类型对象具有哪些功能,我们平常是怎么使用的. 对于python,一切事物都是对象 ...

  3. 关于MarshalByRefObject的解释

    http://www.cnblogs.com/webfpc/archive/2010/03/10/1667101.html 首先了解一下不同应用程序域中的对象的通信方式有两种: 一种是跨应用程序域边界 ...

  4. json_decode

    <?php $json = '{"a":1,"b":2,"c":3,"d":4,"e":5}' ...

  5. html5入门

    1.canvas标签 <canvas id="myCanvas"></canvas><!--canvas标签定义图形,比如图标和其他图像--> ...

  6. mysql SELECT FOR UPDATE语句使用示例

    以MySQL 的InnoDB 为例,预设的Tansaction isolation level 为REPEATABLE READ,在SELECT 的读取锁定主要分为两种方式:SELECT ... LO ...

  7. 《UIP在NIOS上的移植》

    移植环境:Cyclone IV 开发板,网卡芯片为ENC28J60,浏览器(Firefox_24.0.0.5001a) 首先,需要了解网卡芯片ENC28J60,有中文版的说明书:http://wenk ...

  8. JavaScript数组属性与方法

    Array 对象属性 属性 描述 constructor 返回对创建此对象的数组函数的引用. length 设置或返回数组中元素的数目. prototype 使您有能力向对象添加属性和方法. Arra ...

  9. R语言 推荐算法 recommenderlab包

    recommend li_volleyball 2016年3月20日 library(recommenderlab) library(ggplot2) # data(MovieLense) dim(M ...

  10. R语言练习(二)

    op <- par(mfrow = c(2, 2)) #设置画布 p2 <- curve(x^2, 0, 1) #绘制曲线 legend("topleft", inse ...