簡體   English   中英

git 如何從 packfiles 重新創建 deltified 對象?

[英]How does git recreate deltified objects from packfiles?

git如何解析packfile? 我似乎沒有找到任何信息的一個關鍵步驟是 git 如何處理包文件中的 deltified 對象。 我發現的一個很好的資源是 git 文檔,我再也找不到了。 這里有一個類似的副本。 我知道 git 會壓縮它保存在對象目錄中的各種數據,例如提交、樹、blob 等,還有 Delta 對象,其中基礎數據以某種方式與 delta 數據連接。 以下是object 類型的列表:OBJ_COMMIT、OBJ_TREE、OBJ_BLOB、OBJ_TAG、OBJ_OFS_DELTA、OBJ_REF_DELTA。 我也知道有兩種類型的操作,即復制和插入,但我不清楚這些操作如何從包文件中重建修改后的文件。

我還在這里找到了一個相當不錯的指南。

說,我有一個 OBJ_REF_DELTA object 坐在包文件的某個地方。 在該包文件中,我將能夠從前 20 個字節解析基本 object (並且可能通過存儲在索引文件或其他東西中的偏移量在包文件中找到它)。 然后是 delta 的 zlib 壓縮數據。 解壓后的數據是什么樣子的。 這些是復制片段還是插入片段,或兩者兼而有之? 它說:

增量以源長度和目標長度開始,都編碼為可變長度整數,這對於錯誤檢查很有用,但不是必需的。 在此之后,有一系列指令,可能是“復制”(MSB = 1)或“插入”(MSB = 0)。

通過增量開始,它們是否意味着基礎 object 的 ref 之后的壓縮數據? 不,因為他們說復制指令用於從基礎 object 復制:

復制指令表示我們應該將一個連續的字節塊從基礎 object 復制到 output。 執行此操作需要兩個數字:要復制的第一個字節的位置(偏移量)和要復制的字節數。 這些在每條復制指令之后存儲為 little-endian 可變長度整數; 但是,它們的內容被壓縮了。

那么復制和插入指令實際上在哪里呢? 為什么沒有刪除選項。 我了解到 delta 不是 diff,所以也許這意味着我添加的文件不是 delta,而是 delta 是根據存儲為 blob 或其他東西的兩個文件計算得出的,並且 delta 只能有副本並插入,不刪除。 那是對的嗎?

技術文檔位於 Git 存儲庫中,位於Documentation/technical下。

說,我有一個 OBJ_REF_DELTA object 坐在包文件的某個地方。 在該包文件中,我將能夠從前 20 個字節解析基本 object (並且可能通過存儲在索引文件或其他東西中的偏移量在包文件中找到它)。

是的; 或者,如果這是一個OBJ_REF_DELTA ,則會在此處存儲一個負的相對 position。

對於任何普通的包文件, OBJ_OFS_DELTA object 必須在包文件中。 包文件可能不引用本身不存在的對象。 然而,精簡包違反了此規則,並且OBJ_OFS_DELTA可以引用不在包中的 object,在這種情況下,您必須在其他一些包文件中找到 object 或松散的 ZA8CFDE6331BD59EB2AC966F8。

(多包索引文件,如果存在,為您提供另一種方法來查找包含某些對象的包文件。)

然后是 delta 的 zlib 壓縮數據。 解壓后的數據是什么樣子的。 這些是復制片段還是插入片段,或兩者兼而有之?

兩者當然:

它說:

增量以源長度和目標長度開始,都編碼為可變長度整數,這對於錯誤檢查很有用,但不是必需的。 在此之后,有一系列指令,可能是“復制”(MSB = 1)或“插入”(MSB = 0)。

通過增量開始,它們是否意味着基礎 object 的 ref 之后的壓縮數據? 不,因為他們說復制指令用於從基礎 object 復制...

正確的。 我們有這些不必要的錯誤檢查值,如果我們願意,我們可以完全忽略它們。 然后我們有說明,內容為:

  • 從增量基礎 object 在增量基礎 object 的偏移量 O 處復制 N 個字節

(其中有兩個可變長度的數字),或者:

  • 插入 N 個字節

(其中有一個可變長度的數字)。 這些數字被巧妙地編碼以節省空間,但忽略巧妙之處,讓我們假設我們有一個 N 和一個 O(用於復制)或 N(用於插入):

為什么沒有刪除選項?

你什么時候用一個? 假設我們想在偏移量 100 處獲取前 10 個字節,然后在偏移量 6 處獲取接下來的 32 個字節。結果是 42 個字節長。 您想刪除這 42 個字節中的哪一個? 為什么? 為什么我們不只占用 9 個字節或 31 個字節?

你可能會說:好吧,如果我可以取 32 個字節並在中間刪除一個字節,我會得到我想要的 31 個字節,但我們可以將其編碼為“在偏移量 6 處取 15 個字節,然后在偏移量 22 處取 16 個字節”。 稍長一些,因為我們必須為每個編碼一個 N 和 O,而不是一個 N-and-O 和一個 delete-N,但同時它也稍微一些,因為如果我們一個刪除,我們需要刪除位置的偏移量。 所以最后只是洗了。

我們仍然需要“插入 N 個字節”操作,因為我們可能必須插入在任何現有 object 中都不會出現的inconceivable的字節序列。 缺少這一點,我們需要每個可能的字節至少包含 1 個的對象(一個包含所有 256 個可能字節的單個 object 就足夠了)——但這將比我們簡單的“插入 N”更有效和更明顯。

那么復制和插入指令實際上在哪里呢?

整個 object( OBJ_REF_DELTAOBJ_OFS_DELTA )只包含這些指令 我們將從一些現有的 object 中復制一些塊,並在這些復制的部分或全部之前、之間和/或之后插入一些其他塊,結果是最終的 object。

...所以也許這意味着我對文件的添加不是增量,而是增量是根據存儲為 blob 或其他東西的兩個文件計算得出的,並且增量只能具有復制和插入而不能刪除. 那是對的嗎?

這確實是正確的。 Git starts with "loose-equivalent objects", at least conceptually, and compresses object O k against object O j with each object considered as a single total byte sequence. 壓縮器嘗試對盡可能多的候選對象O 0O 1O 2 ,...,因為它覺得值得嘗試; 獲得“最佳”結果的就是最終結果。 請注意, O k現在位於可以用作下一個 object O l的基礎對象的事物的“窗口”中,依此類推; 無論Ok是否最終被壓縮,這都是正確的。

(有一個最大鏈長度,所以在某些時候,對象本身必須從必須從必須從必須構建的對象構建的對象構建,等等,不再 go 到 window 中。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM