Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-fast-import 最後更新於 2.45.0

名稱

git-fast-import - 快速 Git 資料匯入器的後端

概要

frontend | git fast-import [<options>]

描述

這個程式通常不是終端使用者想要直接執行的程式。大多數終端使用者想要使用現有的前端程式之一,該程式會剖析特定類型的外部來源,並將儲存在其中的內容饋送至git fast-import

fast-import 從標準輸入讀取混合的命令/資料串流,並將一個或多個 packfile 直接寫入到目前的儲存庫中。當在標準輸入上收到 EOF 時,fast-import 會寫出已更新的分支和標籤 ref,完全使用新匯入的資料更新目前的儲存庫。

fast-import 後端本身可以匯入到空的儲存庫(已由git init初始化的儲存庫)中,或逐步更新現有的已填入資料的儲存庫。是否支援從特定的外部來源進行逐步匯入,取決於使用的前端程式。

選項

--force

強制更新已修改的現有分支,即使這樣做會導致遺失提交(因為新的提交不包含舊的提交)。

--quiet

停用 --stats 顯示的輸出,使 fast-import 在成功時通常保持靜默。但是,如果匯入串流具有旨在顯示使用者輸出的指令(例如 progress 指令),仍會顯示相應的訊息。

--stats

顯示一些關於 fast-import 已建立的物件、它們儲存到的 packfile,以及 fast-import 在這次執行期間使用的記憶體的基本統計資料。目前預設會顯示此輸出,但可以使用 --quiet 來停用。

--allow-unsafe-features

許多命令列選項可以藉由使用 featureoption 命令作為 fast-import 串流的一部分提供。但是,其中一些選項是不安全的(例如,允許 fast-import 存取儲存庫外部的檔案系統)。這些選項預設為停用,但可以藉由在命令列上提供此選項來允許。這目前只會影響 export-marksimport-marksimport-marks-if-exists 功能命令。

Only enable this option if you trust the program generating the
fast-import stream! This option is enabled automatically for
remote-helpers that use the `import` capability, as they are
already trusted to run their own code.

前端選項

--cat-blob-fd=<fd>

將對 get-markcat-blobls 查詢的回應寫入到檔案描述元 <fd> 而非 stdout。允許將預定給終端使用者的 progress 輸出與其他輸出分開。

--date-format=<fmt>

指定前端將在 authorcommittertagger 命令中提供給 fast-import 的日期類型。請參閱下面的「日期格式」以取得有關支援的格式及其語法的詳細資訊。

--done

如果串流結尾沒有 done 命令,則終止並發生錯誤。這個選項對於偵測導致前端在開始寫入串流之前終止的錯誤可能很有用。

標記檔案的位置

--export-marks=<file>

完成時,將內部標記表格傾印到 <file>。標記會逐行寫入為 :markid SHA-1。前端可以使用這個檔案來驗證完成後的匯入,或在增量執行之間儲存標記表格。由於 <file> 僅在檢查點(或完成時)開啟和截斷,因此也可以安全地將相同的路徑給予 --import-marks。

--import-marks=<file>

在處理任何輸入之前,載入 <file> 中指定的標記。輸入檔案必須存在、必須可讀,並且必須使用與 --export-marks 產生的格式相同的格式。可以提供多個選項來匯入多組標記。如果標記定義為不同的值,則最後一個檔案獲勝。

--import-marks-if-exists=<file>

與 --import-marks 類似,但如果檔案不存在,則會靜默地跳過檔案,而不是發生錯誤。

--[no-]relative-marks

在指定 --relative-marks 之後,使用 --import-marks= 和 --export-marks= 指定的路徑會相對於目前儲存庫中的內部目錄。在 git-fast-import 中,這表示路徑相對於 .git/info/fast-import 目錄。但是,其他匯入器可能會使用不同的位置。

相對和非相對標記可以透過將 --(no-)-relative-marks 與 --(import|export)-marks= 選項交錯來組合。

子模組重寫

--rewrite-submodules-from=<name>:<file>
--rewrite-submodules-to=<name>:<file>

將由 <name> 指定的子模組的物件 ID,從 from <file> 中使用的值重寫為 to <file> 中使用的值。from 標記應該是由 git fast-export 建立的,而 to 標記應該是在匯入同一個子模組時由 git fast-import 建立的。

<name> 可以是任何不包含冒號字元的任意字串,但在指定對應標記時,必須在這兩個選項中使用相同的值。可以使用 <name> 的不同值來指定多個子模組。如果沒有以對應的配對方式使用這些選項,就會發生錯誤。

當將儲存庫從一個雜湊演算法轉換為另一個雜湊演算法時,這些選項主要很有用;如果沒有這些選項,fast-import 在遇到子模組時將會失敗,因為它無法將物件 ID 寫入新的雜湊演算法。

效能和壓縮調整

--active-branches=<n>

一次保持活動狀態的分支最大數目。如需詳細資訊,請參閱下面的「記憶體使用」。預設值為 5。

--big-file-threshold=<n>

fast-import 將嘗試為其建立差異的 blob 的最大大小(以位元組表示)。預設值為 512m (512 MiB)。某些匯入器可能希望在記憶體受限的系統上降低此值。

--depth=<n>

blob 和樹狀結構差異的最大差異深度。預設值為 50。

--export-pack-edges=<file>

在建立 packfile 之後,將一行資料列印到 <file>,其中列出 packfile 的檔案名稱和寫入到該 packfile 的每個分支上的最後一次提交。在匯入總物件集超過 4 GiB packfile 限制的專案之後,此資訊可能很有用,因為這些提交可以用作呼叫git pack-objects期間的邊緣點。

--max-pack-size=<n>

每個輸出 packfile 的最大大小。預設值為無限制。

fastimport.unpackLimit

請參閱 git-config[1]

效能

fast-import 的設計使其能夠在最小的記憶體使用和處理時間內匯入大型專案。假設前端能夠跟上 fast-import 並向其饋送穩定的資料串流,則在相當簡陋(約 2,000 美元)的硬體上,通常只需 1-2 小時即可完成具有 10 年以上歷史和包含 100,000 多次個別提交的專案的匯入時間。

大多數瓶頸似乎都在外部來源資料存取(來源無法以足夠快的速度擷取修訂版本)或磁碟 IO(fast-import 的寫入速度與磁碟接收資料的速度一樣快)。如果來源資料儲存在與目標 Git 儲存庫不同的磁碟機上,匯入速度將會更快(因為 IO 爭用較少)。

開發成本

一個典型的快速匯入前端程式,程式碼大約是 200 行的 Perl/Python/Ruby 程式碼。大多數開發人員都可以在幾個小時內建立可運作的匯入器,即使這是他們第一次接觸快速匯入,有時甚至是第一次接觸 Git。鑑於大多數轉換工具都是用過即丟(使用一次,永不回頭),這是一個理想的情況。

平行操作

如同 git pushgit fetch,fast-import 處理的匯入可以安全地與平行的 git repack -a -dgit gc 調用,或任何其他 Git 操作(包括 git prune,因為 fast-import 永遠不會使用鬆散物件)並行執行。

fast-import 不會鎖定它正在積極匯入的分支或標籤參考。匯入之後,在其參考更新階段,fast-import 會測試每個現有的分支參考,以驗證更新將會是快速前進更新(參考中儲存的提交包含在要寫入的提交的新歷史記錄中)。如果更新不是快速前進更新,fast-import 將會跳過更新該參考,而是列印警告訊息。fast-import 將始終嘗試更新所有分支參考,並且不會在第一次失敗時停止。

可以使用 --force 強制更新分支,但建議僅在其他情況下為靜態的儲存庫上使用。對於初始匯入到空儲存庫中,不需要使用 --force。

技術討論

fast-import 在記憶體中追蹤一組分支。在匯入過程中,可以隨時透過在輸入串流上傳送 commit 命令來建立或修改任何分支。這種設計允許前端程式同時處理無限數量的分支,並按照它們從來源資料中可用的順序產生提交。它還大大簡化了前端程式。

fast-import 不使用或變更目前的工作目錄,或其中的任何檔案。(但是,它確實會更新由 GIT_DIR 引用的目前 Git 儲存庫。)因此,匯入前端程式可以使用工作目錄來達到自己的目的,例如從外部來源提取檔案修訂版本。這種忽略工作目錄的做法也讓 fast-import 可以非常快速地執行,因為它不需要在分支之間切換時執行任何耗費成本的檔案更新操作。

輸入格式

除了原始檔案資料(Git 不會解釋)之外,fast-import 輸入格式是以文字(ASCII)為基礎。這種基於文字的格式簡化了前端程式的開發和除錯,尤其是在使用 Perl、Python 或 Ruby 等高階語言時。

fast-import 對其輸入非常嚴格。在下面我們說 SP 時,我們指的是正好一個空格。同樣地,LF 表示一個(且只有一個)換行符號,而 HT 表示一個(且只有一個)水平定位字元。提供額外的空白字元會導致意想不到的結果,例如分支名稱或檔案名稱在其名稱中帶有前導或尾隨空格,或者在遇到意外輸入時提早終止 fast-import。

串流註解

為了協助除錯前端程式,fast-import 會忽略任何以 #(ASCII 井號/雜湊)開頭的行,直到包括行尾 LF。註解行可以包含任何不包含 LF 的位元組序列,因此可以用來包含任何可能特定於前端程式的詳細除錯資訊,並在檢查 fast-import 資料串流時很有用。

日期格式

支援以下日期格式。前端程式應透過在 --date-format=<fmt> 命令列選項中傳遞格式名稱,來選擇它將用於這次匯入的格式。

raw

這是 Git 原生格式,為 <time> SP <offutc>。如果未指定 --date-format,它也是 fast-import 的預設格式。

事件的時間由 <time> 指定為自 UNIX 紀元(UTC 1970 年 1 月 1 日午夜)以來的秒數,並寫為 ASCII 十進位整數。

本地偏移由 <offutc> 指定為與 UTC 的正或負偏移。例如,EST(比 UTC 晚 5 小時)在 <tz> 中將表示為「-0500」,而 UTC 為「+0000」。本地偏移不會影響 <time>;它僅用作建議,以幫助格式化常式顯示時間戳記。

如果來源材料中沒有本地偏移,請使用「+0000」或最常見的本地偏移。例如,許多組織的 CVS 儲存庫只有位於同一地點和時區的使用者才能存取。在這種情況下,可以假設一個合理的與 UTC 的偏移。

rfc2822 格式不同,此格式非常嚴格。格式化的任何變化都會導致 fast-import 拒絕該值,並且還可能會對數值執行一些健全性檢查。

raw-permissive

這與 raw 相同,只是不會對數值紀元和本地偏移執行健全性檢查。當嘗試篩選或匯入具有例如錯誤時區值的現有歷史記錄時,這可能很有用。

rfc2822

這是 RFC 2822 中描述的標準日期格式。

一個範例值是「Tue Feb 6 11:22:18 2007 -0500」。Git 剖析器很準確,但有點寬鬆。它與 git am 在套用從電子郵件收到的修補程式時使用的剖析器相同。

某些格式錯誤的字串可能會被接受為有效的日期。在其中某些情況下,Git 仍然能夠從格式錯誤的字串中取得正確的日期。還有一些類型的格式錯誤字串,Git 會錯誤地剖析,但仍然認為它們有效。嚴重格式錯誤的字串將會被拒絕。

與上面的 raw 格式不同,RFC 2822 日期字串中包含的時區/UTC 偏移資訊用於將日期值調整為 UTC,然後再儲存。因此,此資訊盡可能準確非常重要。

如果來源材料使用 RFC 2822 樣式的日期,則前端程式應讓 fast-import 處理剖析和轉換(而不是嘗試自行處理),因為 Git 剖析器已在實際應用中經過充分測試。

如果來源材料已使用 UNIX 紀元格式、可以被哄騙以該格式給出日期,或其格式容易轉換為該格式,則前端程式應優先使用 raw 格式,因為剖析中沒有歧義。

now

一律使用目前的時間和時區。對於 <when>,必須始終提供文字 now

這是一種玩具格式。這個系統的目前時間和時區總是在 fast-import 建立時複製到識別字串中。無法指定不同的時間或時區。

提供此特定格式是因為它簡短易於實作,並且對於想要立即建立新提交,而無需使用工作目錄或 git update-index 的程序可能很有用。

如果在 commit 中使用了單獨的 authorcommitter 命令,則時間戳記可能不匹配,因為系統時鐘將會被輪詢兩次(每個命令一次)。確保作者和提交者身分資訊都具有相同時間戳記的唯一方法是省略 author(因此從 committer 複製)或使用 now 以外的日期格式。

命令

fast-import 接受多個命令來更新目前的儲存庫並控制目前的匯入過程。稍後會詳細討論(包含範例)每個命令。

commit

透過建立新提交並更新分支以指向新建立的提交,來建立新分支或更新現有分支。

tag

從現有的提交或分支建立帶註解的標籤物件。此命令不支援輕量級標籤,因為不建議使用它們來記錄時間上有意義的點。

reset

將現有分支(或新分支)重設為特定修訂版本。必須使用此命令來將分支變更為特定修訂版本,而無需對其進行提交。

blob

將原始檔案資料轉換為 blob,以供將來在 commit 命令中使用。此命令是可選的,不需要執行匯入。

alias

記錄標記引用給定的物件,而無需先建立任何新物件。使用 --import-marks 並引用遺失的標記會導致 fast-import 失敗,因此別名可以提供一種方法,將其他修剪的提交設定為有效的值(例如,最近的非修剪祖先)。

checkpoint

強制 fast-import 關閉目前的封裝檔案,產生其唯一的 SHA-1 總和檢查碼和索引,並啟動一個新的封裝檔案。此命令是可選的,不需要執行匯入。

progress

導致 fast-import 將整行回顯到其自己的標準輸出。此命令是可選的,不需要執行匯入。

done

標記串流的結尾。除非使用 --done 命令列選項或 feature done 命令請求 done 功能,否則此命令是可選的。

get-mark

導致 fast-import 將對應於標記的 SHA-1 列印到使用 --cat-blob-fd 設定的檔案描述符,如果未指定則列印到 stdout

cat-blob

使 fast-import 以 cat-file --batch 格式將 blob 列印到使用 --cat-blob-fd 設定的檔案描述符,如果未指定則列印到 stdout

ls

使 fast-import 以 ls-tree 格式將描述目錄條目的行列印到使用 --cat-blob-fd 設定的檔案描述符,如果未指定則列印到 stdout

feature

啟用指定的功能。這要求 fast-import 支援指定的功能,如果不支持則中止。

option

指定在 OPTIONS 下列出的任何不改變流語義的選項,以滿足前端的需求。此命令是可選的,執行導入並不需要它。

commit

使用新的提交建立或更新分支,記錄對專案的一個邏輯變更。

	'commit' SP <ref> LF
	mark?
	original-oid?
	('author' (SP <name>)? SP LT <email> GT SP <when> LF)?
	'committer' (SP <name>)? SP LT <email> GT SP <when> LF
	('encoding' SP <encoding>)?
	data
	('from' SP <commit-ish> LF)?
	('merge' SP <commit-ish> LF)*
	(filemodify | filedelete | filecopy | filerename | filedeleteall | notemodify)*
	LF?

其中 <ref> 是要在其上進行提交的分支名稱。通常,分支名稱在 Git 中以 refs/heads/ 作為前綴,因此導入 CVS 分支符號 RELENG-1_0 會使用 refs/heads/RELENG-1_0 作為 <ref> 的值。<ref> 的值必須是 Git 中的有效 refname。由於 LF 在 Git refname 中無效,因此這裡不支援任何引用或跳脫語法。

可以選擇性地出現一個 mark 命令,請求 fast-import 保存對新建立的提交的引用,供前端將來使用(格式見下文)。前端通常會標記它們建立的每個提交,從而允許從任何導入的提交建立未來分支。

committer 之後的 data 命令必須提供提交訊息(data 命令的語法見下文)。要導入空的提交訊息,請使用長度為 0 的數據。提交訊息是自由形式的,並且不被 Git 解釋。目前它們必須以 UTF-8 編碼,因為 fast-import 不允許指定其他編碼。

可以包含零個或多個 filemodifyfiledeletefilecopyfilerenamefiledeleteallnotemodify 命令,以在建立提交之前更新分支的內容。這些命令可以按任意順序提供。但是,建議在同一提交中,filedeleteall 命令應先於所有 filemodifyfilecopyfilerenamenotemodify 命令,因為 filedeleteall 會清除分支(見下文)。

命令後的 LF 是可選的(以前是必需的)。請注意,由於向後相容性的原因,如果提交以 data 命令結束(即它沒有 frommergefilemodifyfiledeletefilecopyfilerenamefiledeleteallnotemodify 命令),則可以在命令結尾處出現兩個 LF 命令,而不僅僅是一個。

author

如果作者資訊可能與提交者資訊不同,則可以選擇性地出現 author 命令。如果省略 author,則 fast-import 將自動使用提交者的資訊作為提交的作者部分。有關 author 中欄位的描述,請參見下文,因為它們與 committer 相同。

committer

committer 命令指示誰進行了此提交,以及他們何時進行的。

這裡 <name> 是此人的顯示名稱(例如「Com M Itter」),<email> 是此人的電子郵件地址(「cm@example.com」)。LTGT 是文字的小於 (\x3c) 和大於 (\x3e) 符號。這些是必要的,以便將電子郵件地址與行中的其他欄位分隔開。請注意,<name><email> 是自由形式的,可以包含任何位元組序列,但 LTGTLF 除外。<name> 通常以 UTF-8 編碼。

變更的時間由 <when> 指定,使用由 --date-format=<fmt> 命令列選項選擇的日期格式。有關支援的格式及其語法,請參閱上面的「日期格式」。

encoding

可選的 encoding 命令指示提交訊息的編碼。大多數提交都是 UTF-8 編碼,並且省略了編碼,但這允許將提交訊息導入 Git,而無需先重新編碼它們。

from

from 命令用於指定從哪個提交初始化此分支。此修訂版本將是新提交的第一個祖先。在此提交中建構的樹的狀態將從 from 提交時的狀態開始,並由此次提交中的內容修改進行變更。

在新分支的第一次提交中省略 from 命令將導致 fast-import 建立沒有祖先的提交。這往往僅適用於專案的初始提交。如果前端在建立新分支時從頭開始建立所有檔案,則可以使用 merge 命令來代替 from,以便從空的樹開始提交。通常希望在現有分支上省略 from 命令,因為該分支上的當前提交會自動假定為新提交的第一個祖先。

由於 LF 在 Git refname 或 SHA-1 表達式中無效,因此 <commit-ish> 中不支援任何引用或跳脫語法。

這裡 <commit-ish> 是以下任何一項

  • fast-import 的內部分支表中已有的現有分支的名稱。如果 fast-import 不知道該名稱,則會將其視為 SHA-1 表達式。

  • 標記參考,:<idnum>,其中 <idnum> 是標記號碼。

    fast-import 使用 : 來表示標記參考的原因是,此字元在 Git 分支名稱中是不合法的。前導的 : 可以輕鬆區分標記 42 (:42) 和分支 42 (42refs/heads/42),或者恰好僅由十進制數字組成的縮寫 SHA-1。

    必須先聲明標記(通過 mark),然後才能使用它們。

  • 完整的 40 位元組或縮寫的提交 SHA-1(以十六進制表示)。

  • 任何解析為提交的有效 Git SHA-1 表達式。有關詳細資訊,請參閱 gitrevisions[7] 中的「指定修訂版本」。

  • 特殊的 null SHA-1(40 個零)指定要刪除分支。

從當前分支值重新啟動增量導入的特殊情況應寫為

	from refs/heads/branch^0

^0 後綴是必要的,因為 fast-import 不允許分支從自身開始,並且分支是在從輸入讀取 from 命令之前在記憶體中建立的。新增 ^0 將強制 fast-import 通過 Git 的修訂版本解析函式庫解析提交,而不是其內部分支表,從而載入該分支的現有值。

merge

包含一個額外的祖先提交。額外的祖先連結不會更改在此提交處建構樹狀態的方式。如果在建立新分支時省略了 from 命令,則第一個 merge 提交將是當前提交的第一個祖先,並且分支將從沒有任何檔案開始。fast-import 允許每個提交有無限數量的 merge 命令,從而建立 n 向合併。

這裡 <commit-ish>from 也接受的任何提交規格表達式(見上文)。

filemodify

包含在 commit 命令中,以新增新檔案或變更現有檔案的內容。此命令有兩種不同的方式來指定檔案的內容。

外部資料格式

檔案的資料內容已由先前的 blob 命令提供。前端只需要連線它。

	'M' SP <mode> SP <dataref> SP <path> LF

這裡通常 <dataref> 必須是先前 blob 命令設定的標記參考 (:<idnum>),或是現有 Git blob 物件的完整 40 位元組 SHA-1。如果 <mode>040000,則 <dataref> 必須是現有 Git 樹物件的完整 40 位元組 SHA-1,或是使用 --import-marks 設定的標記參考。

內聯資料格式

尚未提供檔案的資料內容。前端希望將其作為此修改命令的一部分提供。

	'M' SP <mode> SP 'inline' SP <path> LF
	data

有關 data 命令的詳細描述,請參閱下文。

在兩種格式中,<mode> 是檔案條目的類型,以八進制指定。Git 僅支援以下模式

  • 100644644:一般(不可執行)檔案。大多數專案中的大多數檔案都使用此模式。如果有疑問,這就是您想要的。

  • 100755755:一般但可執行的檔案。

  • 120000:符號連結,檔案的內容將是連結目標。

  • 160000:gitlink,物件的 SHA-1 引用另一個儲存庫中的提交。Git 連結只能通過 SHA 或通過提交標記指定。它們用於實作子模組。

  • 040000:子目錄。子目錄只能通過 SHA 或通過使用 --import-marks 設定的樹標記指定。

在兩種格式中,<path> 是要新增(如果尚不存在)或修改(如果已存在)的檔案的完整路徑。

<path> 可以寫為未引用的位元組或 C 風格的引用字串。

<path> 不是以雙引號 (") 開頭時,它是未引用的字串,並且會被解析為沒有任何跳脫序列的文字位元組。但是,如果檔名包含 LF 或以雙引號開頭,則不能將其表示為未引用的字串,並且必須引用。此外,如果 filecopyfilerename 中的來源 <path> 包含 SP,則必須引用它。

<path> 以雙引號 (") 開頭時,它是一個 C 語言風格的引號字串,其中完整檔名被一對雙引號包圍,並使用跳脫序列。某些字元必須以反斜線作為前綴來跳脫:LF 寫成 \n,反斜線寫成 \\,雙引號寫成 \"。某些字元可以選擇性地使用跳脫序列來表示:\a 表示響鈴,\b 表示退格,\f 表示換頁,\n 表示換行,\r 表示歸位,\t 表示水平製表符,以及 \v 表示垂直製表符。任何位元組都可以用 3 位數的八進位碼表示(例如,\033)。所有檔名都可以表示為引號字串。

<path> 必須使用 UNIX 風格的目錄分隔符號(正斜線 /),且其值必須為正規形式。也就是說,它不能

  • 包含空的目錄元件 (例如,foo//bar 無效),

  • 以目錄分隔符號結尾 (例如,foo/ 無效),

  • 以目錄分隔符號開頭 (例如,/foo 無效),

  • 包含特殊元件 ... (例如,foo/./barfoo/../bar 無效)。

樹的根目錄可以用空字串作為 <path> 來表示。

<path> 不能包含 NUL 字元,無論是以字面形式還是以跳脫序列 \000 的形式。建議 <path> 始終使用 UTF-8 編碼。

filedelete

包含在 commit 命令中,用於從分支中移除檔案或遞迴刪除整個目錄。如果檔案或目錄的移除使其父目錄為空,則父目錄也會自動移除。此操作會向上層層遞迴,直到到達第一個非空目錄或根目錄。

	'D' SP <path> LF

此處的 <path> 是要從分支中移除的檔案或子目錄的完整路徑。有關 <path> 的詳細說明,請參閱上面的 filemodify

filecopy

遞迴地將現有的檔案或子目錄複製到分支內的不同位置。現有的檔案或目錄必須存在。如果目的地存在,它將被從來源複製的內容完全取代。

	'C' SP <path> SP <path> LF

此處第一個 <path> 是來源位置,第二個 <path> 是目的地位置。有關 <path> 的詳細說明,請參閱上面的 filemodify。若要使用包含 SP 的來源路徑,則必須引用該路徑。

filecopy 命令會立即生效。一旦來源位置被複製到目的地,任何未來應用於來源位置的命令都不會影響副本的目的地。

filerename

將現有的檔案或子目錄重新命名到分支內的不同位置。現有的檔案或目錄必須存在。如果目的地存在,它將被來源目錄取代。

	'R' SP <path> SP <path> LF

此處第一個 <path> 是來源位置,第二個 <path> 是目的地位置。有關 <path> 的詳細說明,請參閱上面的 filemodify。若要使用包含 SP 的來源路徑,則必須引用該路徑。

filerename 命令會立即生效。一旦來源位置被重新命名到目的地,任何未來應用於來源位置的命令都會在那裡建立新的檔案,而不會影響重新命名的目的地。

請注意,filerenamefilecopy 後接對來源位置的 filedelete 相同。使用 filerename 會有輕微的效能優勢,但這種優勢太小,以至於永遠不值得嘗試將來源資料中的刪除/新增配對轉換為重新命名,以用於快速匯入。提供此 filerename 命令只是為了簡化已經具有重新命名資訊且不想費心將其分解為 filecopy 後接 filedelete 的前端。

filedeleteall

包含在 commit 命令中,用於從分支中移除所有檔案(以及所有目錄)。此命令會將內部分支結構重置為不包含任何檔案,讓前端可以隨後從頭開始新增所有感興趣的檔案。

	'deleteall' LF

如果前端不知道(或不在乎知道)目前分支上有哪些檔案,因此無法產生正確的 filedelete 命令來更新內容,則此命令非常有用。

發出 filedeleteall 後接所需的 filemodify 命令來設定正確的內容,會產生與僅傳送所需的 filemodifyfiledelete 命令相同的結果。然而,filedeleteall 方法可能會要求快速匯入在每個活動分支使用稍微多一點的記憶體(即使對於大多數大型專案而言,也少於 1 MiB);因此,鼓勵能夠輕鬆取得提交中僅受影響路徑的前端這樣做。

notemodify

包含在 commit <notes-ref> 命令中,用於新增註解 <commit-ish> 的新註解或變更此註解的內容。在內部,它類似於對 <commit-ish> 路徑上的 filemodify 100644(可能會拆分為子目錄)。不建議使用任何其他命令寫入 <notes-ref> 樹,除了使用 filedeleteall 來刪除此樹中的所有現有註解。此命令有兩種不同的方式來指定註解的內容。

外部資料格式

註解的資料內容已由先前的 blob 命令提供。前端只需要將其連接到要註解的提交。

	'N' SP <dataref> SP <commit-ish> LF

此處的 <dataref> 可以是先前 blob 命令設定的標記參考 (:<idnum>),或是現有 Git blob 物件的完整 40 位元組 SHA-1 值。

內嵌資料格式

註解的資料內容尚未提供。前端希望將其作為此修改命令的一部分提供。

	'N' SP 'inline' SP <commit-ish> LF
	data

有關 data 命令的詳細描述,請參閱下文。

在這兩種格式中,<commit-ish> 都是 from 也接受的任何提交規範運算式(請參閱上方)。

mark

安排快速匯入儲存對目前物件的參考,讓前端可以在未來回憶此物件,而無需知道其 SHA-1 值。此處的目前物件是 mark 命令所在的物件建立命令。這可以是 committagblob,但 commit 是最常見的用法。

	'mark' SP ':' <idnum> LF

其中 <idnum> 是前端指派給此標記的數字。<idnum> 的值表示為 ASCII 十進位整數。值 0 保留且不能用作標記。只能使用大於或等於 1 的值作為標記。

新的標記會自動建立。只需在另一個 mark 命令中重複使用相同的 <idnum>,就可以將現有標記移至另一個物件。

original-oid

提供原始原始碼控制系統中物件的名稱。快速匯入會直接忽略此指令,但是運作在饋送至快速匯入之前修改串流的篩選程序可能會使用此資訊

	'original-oid' SP <object-identifier> LF

其中 <object-identifier> 是不包含 LF 的任何字串。

tag

建立參考特定提交的已註解標籤。若要建立輕量型(未註解)標籤,請參閱下方的 reset 命令。

	'tag' SP <name> LF
	mark?
	'from' SP <commit-ish> LF
	original-oid?
	'tagger' (SP <name>)? SP LT <email> GT SP <when> LF
	data

其中 <name> 是要建立的標籤名稱。

標籤名稱在儲存至 Git 時會自動加上前綴 refs/tags/,因此匯入 CVS 分支符號 RELENG-1_0-FINAL 只會對 <name> 使用 RELENG-1_0-FINAL,而快速匯入會將對應的 ref 寫入為 refs/tags/RELENG-1_0-FINAL

<name> 的值必須是 Git 中有效的 refname,因此可以包含正斜線。由於 LF 在 Git refname 中無效,因此這裡不支援任何引用或跳脫語法。

from 命令與 commit 命令中的相同;詳情請參閱上方。

tagger 命令使用與 commit 中的 committer 相同的格式;詳情也請參閱上方。

tagger 後的 data 命令必須提供已註解標籤訊息(有關 data 命令語法,請參閱下方)。若要匯入空的標籤訊息,請使用長度為 0 的資料。標籤訊息是自由格式的,不會由 Git 解譯。目前它們必須使用 UTF-8 編碼,因為快速匯入不允許指定其他編碼。

不支援在快速匯入期間從快速匯入內簽署已註解的標籤。不建議嘗試包含您自己的 PGP/GPG 簽名,因為前端無法(輕易地)存取通常用於此類簽名的完整位元組集。如果需要簽署,請使用 reset 從快速匯入內建立輕量型標籤,然後使用標準 *git tag* 程序離線建立這些標籤的已註解版本。

reset

建立(或重新建立)指定的具名分支,選擇性地從特定修訂版開始。reset 命令允許前端為現有的分支發出新的 from 命令,或從現有的提交建立新的分支,而無需建立新的提交。

	'reset' SP <ref> LF
	('from' SP <commit-ish> LF)?
	LF?

有關 <ref><commit-ish> 的詳細說明,請參閱上方 commitfrom 下方的說明。

命令後的 LF 是選擇性的(過去是必要的)。

reset 命令也可以用於建立輕量型(未註解)標籤。例如

reset refs/tags/938
from :938

會建立輕量型標籤 refs/tags/938,其參考標記 :938 所參考的任何提交。

blob

請求將一個檔案修訂版寫入封裝檔。修訂版未連接到任何提交;此連接必須在後續的 commit 命令中透過參考指派的標記來建立。

	'blob' LF
	mark?
	original-oid?
	data

此處的標記命令是選擇性的,因為某些前端選擇自行產生 blob 的 Git SHA-1 值,並直接將其饋送至 commit。然而,這通常比它值得做的工作要多,因為標記的儲存成本不高且易於使用。

data

將原始資料(用於作為 blob/檔案內容、提交訊息或已註解標籤訊息)提供給快速匯入。可以使用精確的位元組計數或使用終止行分隔來提供資料。適用於生產品質轉換的實際前端應始終使用精確的位元組計數格式,因為它更強大且效能更好。分隔格式主要用於測試快速匯入。

data 命令的 <raw> 部分中出現的註解行始終被視為資料主體的一部分,因此永遠不會被快速匯入忽略。這使得匯入任何行可能以 # 開頭的檔案/訊息內容是安全的。

精確的位元組計數格式

前端必須指定資料的位元組數。

	'data' SP <count> LF
	<raw> LF?

其中 <count><raw> 內出現的確切位元組數。<count> 的值以 ASCII 十進制整數表示。<raw> 兩側的 LF 不包含在 <count> 中,也不會包含在匯入的資料中。

<raw> 之後的 LF 是可選的(以前是必需的),但建議使用。始終包含它能讓除錯快速匯入串流更容易,因為下一個指令總是從下一行的第 0 列開始,即使 <raw> 並非以 LF 結尾。

分隔格式

分隔符號字串用於標記資料的結尾。fast-import 會透過搜尋分隔符號來計算長度。此格式主要用於測試,不建議用於實際資料。

	'data' SP '<<' <delim> LF
	<raw> LF
	<delim> LF
	LF?

其中 <delim> 是選擇的分隔符號字串。字串 <delim> 不得在 <raw> 內的單獨一行中出現,否則 fast-import 會認為資料比實際提早結束。緊隨 <raw>LF<raw> 的一部分。這是分隔格式的限制之一,無法提供最後一個位元組不是 LF 的資料區塊。

<delim> LF 之後的 LF 是可選的(以前是必需的)。

alias

記錄標記指的是給定的物件,而無需先建立任何新物件。

	'alias' LF
	mark
	'to' SP <commit-ish> LF
	LF?

有關 <commit-ish> 的詳細描述,請參閱上方 from 的說明。

checkpoint

強制 fast-import 關閉目前的 packfile,啟動新的 packfile,並儲存所有目前的分支參考、標籤和標記。

	'checkpoint' LF
	LF?

請注意,當目前的 packfile 達到 --max-pack-size 或 4 GiB 時(以較小者為準),fast-import 會自動切換 packfile。在自動切換 packfile 期間,fast-import 不會更新分支參考、標籤或標記。

由於 checkpoint 可能需要大量的 CPU 時間和磁碟 I/O(以計算整個 pack 的 SHA-1 校驗和、產生對應的索引檔案並更新參考),因此單個 checkpoint 指令可能需要幾分鐘才能完成。

前端可能會選擇在極大且長時間執行的匯入期間,或當他們需要允許其他 Git 流程存取分支時發出檢查點。然而,鑑於一個 30 GiB 的 Subversion 儲存庫可以在約 3 小時內透過 fast-import 載入 Git,因此可能不需要明確的檢查點。

命令後的 LF 是選擇性的(過去是必要的)。

progress

當從輸入串流處理指令時,fast-import 會將整個 progress 行原封不動地印到其標準輸出通道(檔案描述符 1)。否則,此指令不會對目前的匯入或 fast-import 的任何內部狀態產生影響。

	'progress' SP <any> LF
	LF?

指令的 <any> 部分可以包含任何不包含 LF 的位元組序列。指令後的 LF 是可選的。呼叫者可能希望透過 sed 等工具處理輸出,以刪除該行的開頭部分,例如:

frontend | git fast-import | sed 's/^progress //'

checkpoint 之後立即放置 progress 指令,將會在 checkpoint 完成時通知讀取者,並且可以安全地存取 fast-import 更新的參考。

get-mark

導致 fast-import 將對應於標記的 SHA-1 列印到 stdout 或先前使用 --cat-blob-fd 引數安排的檔案描述符。否則,此指令不會對目前的匯入產生任何影響;其目的是擷取稍後提交可能希望在其提交訊息中參考的 SHA-1。

	'get-mark' SP ':' <idnum> LF

有關如何安全讀取此輸出的詳細資訊,請參閱下方的「指令的回應」。

cat-blob

導致 fast-import 將 blob 列印到先前使用 --cat-blob-fd 引數安排的檔案描述符。否則,此指令不會對目前的匯入產生任何影響;其主要目的是擷取可能在 fast-import 記憶體中,但無法從目標儲存庫存取的 blob。

	'cat-blob' SP <dataref> LF

<dataref> 可以是先前設定的標記參考 (:<idnum>) 或 Git blob 的完整 40 位元組 SHA-1,無論是預先存在或準備寫入。

輸出使用與 git cat-file --batch 相同的格式。

<sha1> SP 'blob' SP <size> LF
<contents> LF

此指令可用於 filemodify 指令可出現的位置,允許在提交的中間使用。對於使用內聯指令的 filemodify,它也可以出現在 data 指令之前。

有關如何安全讀取此輸出的詳細資訊,請參閱下方的「指令的回應」。

ls

將關於路徑物件的資訊列印到先前使用 --cat-blob-fd 引數安排的檔案描述符。這允許從活動提交(使用 cat-blob)列印 blob,或從先前的提交複製 blob 或樹狀結構,以用於目前的提交(使用 filemodify)。

ls 指令也可以在 filemodify 指令可以出現的位置使用,允許在提交的中間使用。

從活動提交讀取

此形式只能在 commit 的中間使用。該路徑命名 fast-import 活動提交中的目錄項目。在這種情況下,路徑必須用引號括起來。

	'ls' SP <path> LF
從具名樹狀結構讀取

<dataref> 可以是標記參考 (:<idnum>) 或 Git 標籤、提交或樹狀結構物件的完整 40 位元組 SHA-1,無論是預先存在或等待寫入。路徑是相對於 <dataref> 命名的樹狀結構的頂層。

	'ls' SP <dataref> SP <path> LF

有關 <path> 的詳細說明,請參閱上方的 filemodify

輸出使用與 git ls-tree <tree> -- <path> 相同的格式。

<mode> SP ('blob' | 'tree' | 'commit') SP <dataref> HT <path> LF

<dataref> 代表 <path> 上的 blob、樹狀結構或提交物件,可用於稍後的 *get-mark*、*cat-blob*、*filemodify* 或 *ls* 指令。

如果該路徑上沒有檔案或子樹,*git fast-import* 將會改為報告:

missing SP <path> LF

有關如何安全讀取此輸出的詳細資訊,請參閱下方的「指令的回應」。

feature

要求 fast-import 支援指定的特性,否則如果它不支援,則中止。

	'feature' SP <feature> ('=' <argument>)? LF

指令的 <feature> 部分可以是以下任何一個:

date-format
export-marks
relative-marks
no-relative-marks
force

作用方式如同在指令列中傳遞了帶有前導 -- 的對應指令列選項(請參閱上方的選項)。

import-marks
import-marks-if-exists

與 --import-marks 類似,但有兩個方面不同:首先,每個串流只允許一個 "feature import-marks" 或 "feature import-marks-if-exists" 指令;其次,--import-marks= 或 --import-marks-if-exists 指令列選項會覆寫串流中的任何這些 "feature" 指令;第三,"feature import-marks-if-exists" 類似於對應的指令列選項,會靜默跳過不存在的檔案。

get-mark
cat-blob
ls

要求後端分別支援 *get-mark*、*cat-blob* 或 *ls* 指令。不支援指定指令的 fast-import 版本將會退出,並顯示表示這一點的訊息。這能讓匯入提早因錯誤而退出,並顯示清晰的訊息,而不是在偵測到不支援的指令之前浪費時間在匯入的早期部分。

notes

要求後端支援 *commit* 指令的 *notemodify* (N) 子指令。不支援 notes 的 fast-import 版本將會退出,並顯示表示這一點的訊息。

done

如果串流在沒有 *done* 指令的情況下結束,則會發生錯誤。如果沒有此特性,可能會偵測不到導致前端在串流中方便的位置突然結束的錯誤。例如,如果匯入前端在運作中途停止,而未在其下屬的 git fast-import 實例中發出 SIGTERM 或 SIGKILL,則可能會發生這種情況。

option

處理指定的選項,使 git fast-import 的行為符合前端的需求。請注意,前端指定的選項會被使用者可能指定給 git fast-import 本身的任何選項所覆寫。

    'option' SP <option> LF

指令的 <option> 部分可以包含「選項」章節中列出的任何不變更匯入語意的選項,不帶前導 --,並以相同的方式處理。

選項指令必須是輸入上的第一個指令(不包括 feature 指令),在任何非選項指令之後提供選項指令是錯誤的。

以下指令列選項會變更匯入語意,因此不得作為選項傳遞:

  • date-format

  • import-marks

  • export-marks

  • cat-blob-fd

  • force

done

如果未使用 done 特性,則視為已讀取 EOF。這可以用來告訴 fast-import 提早完成。

如果使用 --done 指令列選項或 feature done 指令,則 done 指令是強制性的,並標記串流的結尾。

對指令的回應

fast-import 寫入的新物件不會立即可用。大多數 fast-import 指令在下一個檢查點(或完成)之前沒有可見的效果。前端可以傳送指令來填寫 fast-import 的輸入管道,而無需擔心它們生效的速度,這透過簡化排程來提高效能。

但是,對於某些前端而言,能夠從正在更新的目前儲存庫讀回資料很有用(例如,當原始資料根據要應用於先前匯入物件的修補程式來描述物件時)。這可以透過透過雙向管道連接前端和 fast-import 來完成

mkfifo fast-import-output
frontend <fast-import-output |
git fast-import >fast-import-output

以這種方式設定的前端可以使用 progressget-marklscat-blob 指令,從正在進行的匯入中讀取資訊。

為了避免死鎖,此類前端必須在執行可能會阻止的 fast-import 寫入之前,完整取用來自 progresslsget-markcat-blob 的任何擱置輸出。

當機報告

如果為 fast-import 提供無效的輸入,它將會以非零結束狀態終止,並在它匯入到的 Git 儲存庫的頂層建立當機報告。當機報告包含內部 fast-import 狀態的快照,以及導致當機的最近指令。

所有最近的指令(包括串流註解、檔案變更和 progress 指令)都會顯示在當機報告內的指令歷程記錄中,但原始檔案資料和提交訊息不包含在當機報告中。此排除可以節省報告檔案中的空間,並減少 fast-import 在執行期間必須執行的緩衝數量。

在寫入當機報告後,fast-import 將會關閉目前的 packfile 並匯出標記表。這允許前端開發人員檢查儲存庫狀態,並從當機的點繼續匯入。修改過的分支和標籤不會在當機期間更新,因為匯入未成功完成。分支和標籤資訊可以在當機報告中找到,如果需要更新,則必須手動套用。

當機範例:

$ cat >in <<END_OF_INPUT
# my very first test commit
commit refs/heads/master
committer Shawn O. Pearce <spearce> 19283 -0400
# who is that guy anyway?
data <<EOF
this is my commit
EOF
M 644 inline .gitignore
data <<EOF
.gitignore
EOF
M 777 inline bob
END_OF_INPUT
$ git fast-import <in
fatal: Corrupt mode: M 777 inline bob
fast-import: dumping crash report to .git/fast_import_crash_8434
$ cat .git/fast_import_crash_8434
fast-import crash report:
    fast-import process: 8434
    parent process     : 1391
    at Sat Sep 1 00:58:12 2007
fatal: Corrupt mode: M 777 inline bob
Most Recent Commands Before Crash
---------------------------------
  # my very first test commit
  commit refs/heads/master
  committer Shawn O. Pearce <spearce> 19283 -0400
  # who is that guy anyway?
  data <<EOF
  M 644 inline .gitignore
  data <<EOF
* M 777 inline bob
Active Branch LRU
-----------------
    active_branches = 1 cur, 5 max
pos  clock name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1)      0 refs/heads/master
Inactive Branches
-----------------
refs/heads/master:
  status      : active loaded dirty
  tip commit  : 0000000000000000000000000000000000000000
  old tree    : 0000000000000000000000000000000000000000
  cur tree    : 0000000000000000000000000000000000000000
  commit clock: 0
  last pack   :
-------------------
END OF CRASH REPORT

提示和技巧

以下訣竅與技巧是從 fast-import 的各種使用者收集而來,並在此以建議的形式提供。

每個提交使用一個標記

在進行儲存庫轉換時,每個提交使用一個獨特的標記 (mark :<n>),並在命令列提供 --export-marks 選項。fast-import 會傾印一個檔案,其中列出每個標記及其對應的 Git 物件 SHA-1。如果前端可以將標記連結回來源儲存庫,則可以透過比較每個 Git 提交與對應的來源修訂版本,輕鬆驗證匯入的準確性和完整性。

對於 Perforce 或 Subversion 等系統而言,這應該相當簡單,因為 fast-import 標記也可以是 Perforce 變更集編號或 Subversion 修訂版本編號。

自由跳過分支

無需費力最佳化前端,使其在匯入期間一次只處理一個分支。儘管這樣做可能會稍微加快 fast-import 的速度,但往往會大幅增加前端程式碼的複雜性。

fast-import 內建的分支 LRU 通常表現良好,而且啟動非活動分支的成本非常低,因此在分支之間跳動幾乎不會影響匯入效能。

處理重新命名

匯入重新命名的檔案或目錄時,只需在對應的提交期間刪除舊名稱並修改新名稱即可。Git 在事後執行重新命名偵測,而不是在提交期間明確執行。

使用標籤修復分支

某些其他 SCM 系統允許使用者從多個並非來自同一個提交/變更集的多個檔案建立標籤。或者建立只是儲存庫中可用檔案子集的標籤。

若未至少進行一次「修復」檔案以符合標籤內容的提交,則無法直接將這些標籤匯入 Git。使用 fast-import 的 reset 命令,將一般分支空間之外的虛擬分支重設為標籤的基本提交,然後提交一個或多個檔案修復提交,最後標記虛擬分支。

例如,由於所有正常分支都儲存在 refs/heads/ 名稱下,請將標籤修復分支命名為 TAG_FIXUP。如此一來,匯入器使用的修復分支就不可能與從來源匯入的真實分支發生命名空間衝突 (名稱 TAG_FIXUP 並非 refs/heads/TAG_FIXUP)。

提交修復時,請考慮使用 merge 將向修復分支提供檔案修訂版本的提交連接起來。這樣做可讓 git blame 等工具追蹤真實的提交歷史記錄,並正確註解來源檔案。

fast-import 終止後,前端需要執行 rm .git/TAG_FIXUP 來移除虛擬分支。

立即匯入,稍後重新封裝

fast-import 完成後,Git 儲存庫就完全有效並可供使用。通常,即使對於相當大的專案 (超過 100,000 個提交),也只需要很短的時間。

但是,必須重新封裝儲存庫才能改善資料局部性和存取效能。在極大的專案上 (特別是使用 -f 和大型 --window 參數時),這也可能需要數小時。由於重新封裝可以與讀取器和寫入器同時安全執行,因此在背景執行重新封裝,並讓它在完成時結束。您無需等待即可探索新的 Git 專案!

如果您選擇等待重新封裝,請勿在重新封裝完成之前嘗試執行基準測試或效能測試。fast-import 輸出的最佳化程度較低的封裝檔案,在實際使用情況中絕不會看到。

重新封裝歷史資料

如果您要重新封裝非常舊的匯入資料 (例如,比去年更舊的資料),請考慮花費一些額外的 CPU 時間,並在執行 git repack 時提供 --window=50 (或更高)。這會花費更長的時間,但也會產生較小的封裝檔案。您只需花費一次時間,而且每個使用您專案的人都會受益於較小的儲存庫。

包含一些進度訊息

您的前端應不時向 fast-import 發出 progress 訊息。訊息的內容完全是自由格式,因此一種建議是,每次目前的提交日期移至下個月時,都輸出目前的月份和年份。您的使用者會因為知道已處理多少資料串流而感覺更好。

封裝檔案最佳化

封裝 blob 時,fast-import 始終嘗試以最後寫入的 blob 為基準進行差異化。除非前端特別安排,否則這可能不是同一個檔案的先前版本,因此產生的差異不會是最小的。產生的封裝檔案會經過壓縮,但不會是最佳的。

可以有效存取單一檔案的所有修訂版本 (例如,讀取 RCS/CVS ,v 檔案) 的前端,可以選擇將該檔案的所有修訂版本提供為一連串連續的 blob 命令。這可讓 fast-import 以彼此為基準進行不同檔案修訂版本的差異化,進而節省最終封裝檔案中的空間。標記可用於在稍後的一連串 commit 命令期間識別個別的檔案修訂版本。

fast-import 建立的封裝檔案不會促進良好的磁碟存取模式。這是因為 fast-import 會依標準輸入接收資料的順序寫入資料,而 Git 通常會在封裝檔案中組織資料,以使最新 (目前提示) 的資料顯示在歷史資料之前。Git 也會將提交叢集在一起,透過更好的快取局部性加快修訂版本遍歷的速度。

因此,強烈建議使用者在 fast-import 完成後,使用 git repack -a -d 重新封裝儲存庫,讓 Git 重新組織封裝檔案,以加快資料存取速度。如果 blob 差異化效果不佳 (請參閱上方),則新增 -f 選項以強制重新計算所有差異,也可以大幅減少最終封裝檔案大小 (減少 30-50% 是很典型的)。

除了執行 git repack 之外,您也可以執行 git gc --aggressive,這也會在匯入後最佳化其他項目 (例如,封裝鬆散的參考)。如同 git-gc[1] 中的「AGGRESSIVE」區段所述,--aggressive 選項將使用 git-repack[1]-f 選項尋找新的差異。基於以上詳述的原因,在 fast-import 後使用 --aggressive 是少數已知值得採用的情況之一。

記憶體使用率

有許多因素會影響 fast-import 執行匯入所需的記憶體量。就像核心 Git 的關鍵區段一樣,fast-import 會使用自己的記憶體配置器來分攤與 malloc 相關的任何額外負荷。實際上,fast-import 往往會將所有 malloc 額外負荷攤銷至 0,因為它使用了大型區塊配置。

每個物件

fast-import 會針對此次執行中寫入的每個物件維護一個記憶體內結構。在 32 位元系統上,該結構為 32 個位元組;在 64 位元系統上,該結構為 40 個位元組 (由於指標大小較大)。在 fast-import 終止之前,不會解除配置表格中的物件。在 32 位元系統上匯入 200 萬個物件約需要 64 MiB 的記憶體。

物件表格實際上是以物件名稱 (唯一的 SHA-1) 為鍵的雜湊表。這種儲存配置可讓 fast-import 重複使用現有或已寫入的物件,並避免將重複的物件寫入輸出封裝檔案。重複的 blob 在匯入中非常常見,通常是因為來源中的分支合併所造成。

每個標記

標記儲存在稀疏陣列中,每個標記使用 1 個指標 (4 個位元組或 8 個位元組,取決於指標大小)。儘管陣列是稀疏的,但仍然強烈建議前端使用介於 1 和 n 之間的標記,其中 n 是此次匯入所需的標記總數。

每個分支

分支分為活動和非活動分支。這兩類別的記憶體使用量有顯著差異。

非活動分支儲存在一個結構中,每個分支使用 96 或 120 個位元組 (分別為 32 位元或 64 位元系統) 以及分支名稱的長度 (通常在 200 個位元組以下)。fast-import 可以輕鬆處理多達 10,000 個非活動分支,而且使用的記憶體低於 2 MiB。

活動分支與非活動分支具有相同的額外負荷,但也包含最近在該分支上修改的每個樹狀結構的複本。如果子樹狀結構 include 自從分支變成活動狀態後就未經過修改,則其內容不會載入記憶體中;但是,如果子樹狀結構 src 自從分支變成活動狀態後已由提交修改,則其內容將載入記憶體中。

由於活動分支會儲存該分支上所包含檔案的中繼資料,因此其記憶體內儲存大小可能會成長到相當大的大小 (請參閱下方)。

fast-import 會根據簡單的最近最少使用演算法,自動將活動分支移至非活動狀態。LRU 鏈會在每個 commit 命令上更新。可以使用命令列中的 --active-branches= 來增加或減少活動分支的最大數目。

每個活動樹狀結構

樹狀結構 (又稱為目錄) 除了其項目所需的記憶體外 (請參閱下方的「每個活動檔案」),僅使用 12 個位元組的記憶體。樹狀結構的成本實際上為 0,因為其額外負荷會分攤在個別的檔案項目中。

每個活動檔案項目

活動樹狀結構中的檔案 (和指向子樹狀結構的指標) 每個項目需要 52 或 64 個位元組 (32/64 位元平台)。為了節省空間,檔案和樹狀結構名稱會彙總在一個通用字串表格中,無論檔案名稱「Makefile」在專案中出現多少次,都只會使用 16 個位元組 (包括字串標頭額外負荷)。

活動分支 LRU 在與檔案名稱字串集區和子樹狀結構的延遲載入結合使用時,可讓 fast-import 在非常有限的記憶體空間中 (每個活動分支低於 2.7 MiB) 有效率地匯入包含超過 2,000 個分支和超過 45,114 個檔案的專案。

訊號

git fast-import 程序傳送 SIGUSR1 會提早結束目前的封裝檔案,模擬 checkpoint 命令。不耐煩的操作員可以使用此功能來查看匯入中的物件和參考,但代價是一些額外的執行時間和較差的壓縮。

組態

本節中此行以下的任何內容都是從 git-config[1] 文件選擇性包含的。內容與其中找到的內容相同

fastimport.unpackLimit

如果由 git-fast-import[1] 匯入的物件數低於此限制,則物件將解壓縮至鬆散物件檔案。但是,如果匯入的物件數等於或超過此限制,則封裝將儲存為封裝。從 fast-import 儲存封裝可使匯入作業更快完成,尤其是在緩慢的檔案系統上。如果未設定,則改用 transfer.unpackLimit 的值。

另請參閱

GIT

屬於 git[1] 套件的一部分

scroll-to-top