簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-fast-import 最後更新於 2.50.0

名稱

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

概要

frontend | git fast-import [<options>]

描述

此程式通常不是終端使用者希望直接執行的。大多數終端使用者希望使用現有的前端程式之一,這些程式解析特定型別的外部源,並將其中儲存的內容提供給 git fast-import

fast-import 從標準輸入讀取混合的命令/資料流,並將一個或多個 packfile 直接寫入當前倉庫。當標準輸入收到 EOF 時,fast-import 會寫出更新後的分支和標籤引用,從而使用新匯入的資料完全更新當前倉庫。

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 從 <file> 中使用的值重寫為 <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 和 tree deltification 的最大增量深度。預設為 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 併為其提供持續的資料流,對於擁有 10 年以上歷史幷包含 100,000+ 個獨立提交的專案,匯入時間通常在相當普通的(約 2,000 美元)硬體上僅需 1-2 小時即可完成。

大多數瓶頸似乎出現在外部源資料訪問(源無法足夠快地提取修訂)或磁碟 I/O(fast-import 寫入資料的速度與磁碟接收資料的速度一樣快)方面。如果源資料儲存在與目標 Git 倉庫不同的驅動器上,匯入將執行得更快(由於 I/O 爭用較少)。

開發成本

fast-import 的典型前端通常約有 200 行 Perl/Python/Ruby 程式碼。大多數開發人員能夠在幾個小時內建立可用的匯入器,即使這是他們第一次接觸 fast-import,有時甚至是第一次接觸 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 倉庫,如 GIT_DIR 所引用的那樣。)因此,匯入前端可以將工作目錄用於其自身目的,例如從外部源提取檔案修訂。這種對工作目錄的忽視也使得 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 紀元(1970 年 1 月 1 日午夜,UTC)以來的秒數,並以 ASCII 十進位制整數寫入。

本地偏移由 <offutc> 指定,作為與 UTC 的正或負偏移。例如,EST(比 UTC 晚 5 小時)將透過“-0500”在 <tz> 中表示,而 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

始終使用當前時間和時區。文字 now 必須始終為 <when> 提供。

這是一種玩具格式。系統當前的時間和時區總是在 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 關閉當前 packfile,生成其唯一的 SHA-1 校驗和和索引,並啟動新的 packfile。此命令是可選的,並非執行匯入所必需。

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
	('gpgsig' SP <alg> LF data)?
	('encoding' SP <encoding> LF)?
	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 中有效的引用名稱。由於 LF 在 Git 引用名稱中無效,因此此處不支援引用或轉義語法。

可以選擇出現 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> 命令列選項選擇的日期格式指定。有關支援的格式及其語法的集合,請參見上面的“日期格式”。

gpgsig

可選的 gpgsig 命令用於包含一個對提交資料簽名的 PGP/GPG 簽名。

此處 <alg> 指定用於此簽名的雜湊演算法,可以是 sha1sha256

注意
這是一個高度實驗性的功能,資料流的格式將來可能會更改,不保證相容性。

encoding

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

from

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

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

由於 LF 在 Git 引用名稱或 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] 中的“指定修訂版本”。

  • 特殊的空 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:Git 連結,物件的 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 略有效能優勢,但該優勢非常小,不值得嘗試將源材料中的刪除/新增對轉換為 fast-import 的重新命名。提供此 filerename 命令只是為了簡化已經擁有重新命名資訊且不想費心將其分解為 filecopy 後跟 filedelete 的前端。

filedeleteall

包含在 commit 命令中,用於從分支中刪除所有檔案(以及所有目錄)。此命令將內部分支結構重置為不包含任何檔案,從而允許前端隨後從頭開始新增所有相關檔案。

	'deleteall' LF

如果前端不知道(或不關心知道)分支上當前有哪些檔案,因此無法生成適當的 filedelete 命令來更新內容,那麼此命令將非常有用。

釋出 filedeleteall 後跟所需的 filemodify 命令來設定正確的內容將產生與僅傳送所需的 filemodifyfiledelete 命令相同的結果。filedeleteall 方法可能會要求 fast-import 為每個活動分支使用略多一點的記憶體(即使對於大多數大型專案,也少於 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

安排 fast-import 儲存對當前物件的引用,允許前端將來在不知道其 SHA-1 的情況下召回此物件。此處,當前物件是 mark 命令所出現的物件建立命令。這可以是 committagblob,但 commit 是最常見的用法。

	'mark' SP ':' <idnum> LF

其中 <idnum> 是前端分配給此標記的編號。<idnum> 的值以 ASCII 十進位制整數表示。值 0 被保留,不能用作標記。只有大於或等於 1 的值才能用作標記。

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

original-oid

提供原始原始碼控制系統中物件的名稱。fast-import 將簡單地忽略此指令,但在將其饋送到 fast-import 之前對流進行操作和修改的過濾過程可能會用到此資訊

	'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 將只使用 RELENG-1_0-FINAL 作為 <name>,fast-import 將把相應的引用寫為 refs/tags/RELENG-1_0-FINAL

<name> 的值必須是 Git 中有效的引用名稱,因此可能包含正斜槓。由於 LF 在 Git 引用名稱中無效,因此此處不支援引用或轉義語法。

from 命令與 commit 命令中的用法相同;詳情請參見上文。

tagger 命令的格式與 commit 中的 committer 相同;詳情請參見上文。

tagger 後面的 data 命令必須提供帶註釋的標籤訊息(data 命令語法見下文)。要匯入空標籤訊息,請使用長度為 0 的資料。標籤訊息是自由格式的,Git 不會對其進行解釋。目前它們必須以 UTF-8 編碼,因為 fast-import 不允許指定其他編碼。

fast-import 內部不支援在匯入期間對帶註釋標籤進行簽名。不建議嘗試包含您自己的 PGP/GPG 簽名,因為前端無法(輕易地)訪問通常構成此類簽名的完整位元組集。如果需要簽名,請在 fast-import 內部使用 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

請求將一個檔案修訂寫入 packfile。此修訂未連線到任何提交;此連線必須在後續的 commit 命令中透過引用透過分配的標記引用的 blob 來形成。

	'blob' LF
	mark?
	original-oid?
	data

此處的 mark 命令是可選的,因為一些前端選擇自行生成 blob 的 Git SHA-1,並將其直接提供給 commit。然而,這通常不值得,因為標記儲存成本低且易於使用。

data

向 fast-import 提供原始資料(用作 blob/檔案內容、提交訊息或帶註釋的標籤訊息)。資料可以透過精確的位元組計數或用終止行分隔的方式提供。用於生產質量轉換的實際前端應始終使用精確位元組計數格式,因為它更健壯且效能更好。分隔格式主要用於測試 fast-import。

data 命令的 <raw> 部分中出現的註釋行始終被視為資料正文的一部分,因此 fast-import 絕不會忽略它們。這使得匯入任何行可能以 # 開頭的檔案/訊息內容是安全的。

精確位元組計數格式

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

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

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

<raw> 之後的 LF 是可選的(以前是必需的),但建議包含。始終包含它會使 fast-import 流的除錯更容易,因為下一個命令總是從下一行的第 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,開始一個新的,並儲存所有當前分支引用、標籤和標記。

	'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 倉庫可以透過 fast-import 在大約 3 小時內載入到 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 引數安排的檔案描述符。這允許從活動提交列印 blob(使用 cat-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、tree 或 commit 物件,可在後續的 *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

表現得好像相應的帶有前導 -- 的命令列選項已在命令列上傳遞(參見上文的 OPTIONS)。

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

要求後端支援 *notemodify* (N) 子命令作為 *commit* 命令的一部分。不支援備註的 fast-import 版本將以指示其不支援的訊息退出。

done

如果流結束時沒有 *done* 命令,則報錯。沒有此功能,導致前端在流中某個方便點突然終止的錯誤可能無法檢測到。例如,如果匯入前端在操作中途死亡,而沒有向其下屬的 git fast-import 例項發出 SIGTERM 或 SIGKILL,則可能會發生這種情況。

option

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

    'option' SP <option> LF

命令的 <option> 部分可以包含 OPTIONS 部分中列出的任何不改變匯入語義的選項,不帶前導 --,並以相同方式處理。

選項命令必須是輸入中的第一個命令(不包括功能命令),在任何非選項命令之後給出選項命令是錯誤的。

以下命令列選項會改變匯入語義,因此不能作為選項傳遞

  • 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 內部狀態的快照以及導致崩潰的最新命令。

所有最近的命令(包括流注釋、檔案更改和進度命令)都會顯示在崩潰報告的命令歷史中,但原始檔案資料和提交訊息被排除在崩潰報告之外。這種排除節省了報告檔案中的空間,並減少了 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 輸出的打包檔案並非最優,在實際使用場景中是不會遇到的。

重新打包歷史資料

如果您正在重新打包非常舊的匯入資料(例如,一年多以前的資料),請考慮在執行 git repack 時花費額外的 CPU 時間並提供 --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 開銷分攤到接近於零。

每個物件

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 位元組的記憶體。樹的成本幾乎為零,因為其開銷會分攤到各個檔案條目上。

每個活動檔案條目

活動樹中的檔案(以及指向子樹的指標)每個條目需要 52 或 64 位元組(32/64 位平臺)。為了節省空間,檔案和樹名稱會被彙集到一個公共字串表中,這使得檔名“Makefile”無論在專案中出現多少次,都只需使用 16 位元組(包括字串頭開銷)。

活動分支 LRU 與檔名字串池和子樹的延遲載入相結合,使得 fast-import 能夠在非常有限的記憶體佔用(每個活動分支不到 2.7 MiB)下高效匯入擁有 2,000 多個分支和 45,114 多個檔案的專案。

訊號

SIGUSR1 訊號傳送到 git fast-import 程序可以提前結束當前打包檔案,模擬一個 checkpoint 命令。不耐煩的操作員可以使用此功能來檢視正在進行匯入的物件和引用,代價是增加一些執行時間和更差的壓縮效果。

配置

本節中以下所有內容均從 git-config[1] 文件中選擇性地包含。內容與彼處相同:

fastimport.unpackLimit

如果 git-fast-import[1] 匯入的物件數量低於此限制,則這些物件將被解包成鬆散物件檔案。然而,如果匯入的物件數量等於或超過此限制,則打包將作為一個整體儲存。從 fast-import 儲存打包檔案可以使匯入操作更快完成,尤其是在慢速檔案系統上。如果未設定,則使用 transfer.unpackLimit 的值。

另請參閱

GIT

Git[1] 套件的一部分

scroll-to-top