原文:
一、打包檔案索引
首先, 我們來看一下打包檔案索引, 基本上它只是一系列指向打包檔案內位置的書籤.
打包檔案索引有兩個版本.
版本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
開頭的所有的物件中
s ha1
值 最小的物件在
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程式讀出打包檔案的頭部:
defread_pack_header頭部之後是一系列按照sha值排序的打包物件, 每乙個打包物件包含了頭部和內容.sig
=@session
.recv(4
)ver
=@session
.recv(4
).unpack
("n")[0
]entries
=@session
.recv(4
).unpack
("n")[0
][sig,
ver,
entries
]end
打包檔案的尾部
是該檔案中所有(已排序)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的格式用於git 1.6版本之前,版本2的格式用於git 1.6及以後的版本.但是版本2可以被git 1.5.2及以上的git讀取,同時也被後向移植 backport 到...
git 檔案打包命令
git archive 我的蹩腳英文就不獻醜了大家到這個地方 去看吧 簡單的用法就是 git archive format zip output path to file.zip master 將 master 以zip格式打包到指定檔案還有個更簡單的 git archive v0.1 gzip s...
git 檔案打包命令
git archive 我的蹩腳英文就不獻醜了大家到這個地方 去看吧 簡單的用法就是 git archive format zip output path to file.zip master 將 master 以zip格式打包到指定檔案還有個更簡單的 git archive v0.1 gzip s...