Git打包檔案

2021-07-11 02:08:32 字數 3542 閱讀 8629

原文: 

一、打包檔案索引

首先, 我們來看一下打包檔案索引, 基本上它只是一系列指向打包檔案內位置的書籤.

打包檔案索引有兩個版本.

版本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

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的格式用於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...