原文: 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. Yii2 高级版新建一个 Api 应用

    原文地址:http://www.getyii.com/topic/28 先在项目的根目录下复制一份 backend 为 api: cp backend/ api -r 拷贝 api 环境 cp -a ...

  2. input实时监听value change

    oninput ie9+,otheronpropertychange  ie6-8 js使用 var el = docuemnt.getElementById('id'); if('oninput' ...

  3. 用C语言将搜狗输入法词库转换成QQ拼音输入法词库

    搜狗输入法词库格式: 'ni'kan'xia 你看下 'ni'kan'xia'gai'hou 你看下改后 'ni'kan'xing'ma 你看行吗 'ni'kan'zen'me'yang 你看怎么样 ...

  4. weblogic 的安装和配置

    一.安装 1.1安装weblogic8.1 首先从www.bea.com上下载安装文件platform816_linux32.bin,然后在安装文件所在目录下键入 ./platform816_linu ...

  5. 手把手教你如何把java代码,打包成jar文件以及转换为exe可执行文件

    1.背景: 学习java时,教材中关于如题问题,只有一小节说明,而且要自己写麻烦的配置文件,最终结果却只能转换为jar文件.实在是心有不爽.此篇博客教你如何方便快捷地把java代码,打包成jar文件以 ...

  6. c# 获取系统时间

    //获取日期+时间DateTime.Now.ToString();             // 2008-9-4 20:02:10DateTime.Now.ToLocalTime().ToStrin ...

  7. PHP+MySQL存储数据出现中文乱码的问题

    PHP+MySQL出现中文乱码的原因: 1. MYSQL数据库的编码是utf8,与PHP网页的编码格式不一致,就会造成MYSQL中的中文乱码. 2. 使用MYSQL中创建表.或者选择字段时设置的类型不 ...

  8. 序列化反序列化api(入门级)

    定义: java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 为什么字符串通常也会进行序列化? 对象需要进行序列化的原因:保证对象的状态不变 ...

  9. 全栈工程师是不是必须得会HTML5?

    最近看了很多招聘,都要求前端工程师必须得会HTML5.个人觉得只要会了html,HTML5不会太难,不过全栈工程师要求会的太多了 HTML CSS JavaScript HTML 5 CSS 3 都说 ...

  10. CodeForces 353B Two Heaps

    B. Two Heaps   Valera has 2·n cubes, each cube contains an integer from 10 to 99. He arbitrarily cho ...