# git-fast-import
> 原文: [https://git-scm.com/docs/git-fast-import](https://git-scm.com/docs/git-fast-import)
## 名稱
git-fast-import - 快速Git數據導入器的后端
## 概要
```
frontend | git fast-import [<options>]
```
## 描述
該程序通常不是最終用戶想要直接運行的程序。大多數最終用戶希望使用現有的前端程序之一,該程序解析特定類型的外部源并將存儲在那里的內容提供給 _git fast-import_ 。
fast-import從標準輸入讀取混合命令/數據流,并將一個或多個packfiles直接寫入當前存儲庫。在標準輸入上收到EOF時,快速導入會寫出更新的分支和標記引用,使用新導入的數據完全更新當前存儲庫。
快速導入后端本身可以導入到空存儲庫(已經由 _git init_ 初始化的存儲庫)或者逐步更新現有的已填充存儲庫。是否支持來自特定外部源的增量導入取決于正在使用的前端程序。
## OPTIONS
```
--force
```
強制更新已修改的現有分支,即使這樣做會導致提交丟失(因為新提交不包含舊提交)。
```
--quiet
```
禁用--stats顯示的輸出,快速導入通常在成功時保持靜默。但是,如果導入流具有旨在顯示用戶輸出的指令(例如`progress`指令),則仍將顯示相應的消息。
```
--stats
```
顯示有關快速導入已創建的對象,存儲它們的包文件以及在此運行期間快速導入所使用的內存的一些基本統計信息。顯示此輸出目前是默認值,但可以使用--quiet禁用。
### 前端的選項
```
--cat-blob-fd=<fd>
```
將對`get-mark`,`cat-blob`和`ls`查詢的響應寫入文件描述符< fd>而不是`stdout`。允許最終用戶的`progress`輸出與其他輸出分開。
```
--date-format=<fmt>
```
指定前端將在`author`,`committer`和`tagger`命令中快速導入的日期類型。有關支持哪些格式及其語法的詳細信息,請參閱下面的“日期格式”。
```
--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目錄。但是,其他進口商可能會使用其他位置。
相對和非相對標記可以通過交織 - (無 - ) - 相對標記與 - (import | export)-marks =選項相結合。
### 性能和壓縮調整
```
--active-branches=<n>
```
一次保持活動的最大分支數。有關詳細信息,請參閱下面的“內存使默認值為5。
```
--big-file-threshold=<n>
```
快速導入將嘗試創建增量的blob的最大大小,以字節為單位表示。默認值為512米(512 MiB)。一些進口商可能希望在具有受限內存的系統上降低此值。
```
--depth=<n>
```
最大增量深度,用于blob和樹木劃分。默認值為50。
```
--export-pack-edges=<file>
```
創建包文件后,將一行數據打印到< file>列出packfile的文件名以及寫入該packfile的每個分支上的最后一次提交。導入總對象集超過4 GiB packfile限制的項目后,此信息可能很有用,因為這些提交可以在調用 _git pack-objects_ 時用作邊緣點。
```
--max-pack-size=<n>
```
每個輸出包文件的最大大小。默認值是無限制的。
```
fastimport.unpackLimit
```
見 [git-config [1]](https://git-scm.com/docs/git-config)
## 性能
快速導入的設計允許它以最小的內存使用量和處理時間導入大型項目。假設前端能夠跟上快速導入并為其提供恒定的數據流,那么擁有10年以上歷史且包含100,000多個單獨提交的項目的導入時間通常只需1-2小時即可完成( ?$ 2,000 USD)硬件。
大多數瓶頸似乎是在外部源數據訪問(源無法足夠快地提取修訂版)或磁盤IO(快速導入寫入速度與磁盤將獲取數據一樣快)。如果源數據存儲在與目標Git存儲庫不同的驅動器上(由于較少的IO爭用),導入將運行得更快。
## 發展成本
快速導入的典型前端往往占據大約200行Perl / Python / Ruby代碼。大多數開發人員能夠在短短幾個小時內創建工作進口商,即使這是他們第一次快速導入,有時甚至是Git。這是一個理想的情況,因為大多數轉換工具都是丟棄的(使用一次,永不回頭)。
## 并行操作
像 _git push_ 或 _git fetch_ 一樣,快速導入處理的導入可以安全地與并行`git repack -a -d`或`git gc`調用或任何其他Git操作(包括_)一起運行git prune_ ,因為松散的對象永遠不會被快速導入使用)。
快速導入不會鎖定分支或標記引用它正在主動導入。導入之后,在其ref更新階段,快速導入測試每個現有分支ref以驗證更新將是快進更新(存儲在ref中的提交包含在要寫入的提交的新歷史中)。如果更新不是快進更新,則快速??導入將跳過更新該ref,而是打印警告消息。快速導入將始終嘗試更新所有分支引用,并且不會在第一次失敗時停止。
可以使用--force強制分支更新,但建議僅在其他安靜的存儲庫上使用它。初始導入空存儲庫不需要使用--force。
## 技術討論
快速導入跟蹤內存中的一組分支。通過在輸入流上發送`commit`命令,可以在導入過程中的任何時刻創建或修改任何分支。此設計允許前端程序同時處理無限數量的分支,按源數據中可用的順序生成提交。它還大大簡化了前端程序。
fast-import不使用或更改當前工作目錄或其中的任何文件。 (但它會更新當前的Git存儲庫,由`GIT_DIR`引用。)因此,導入前端可以將工作目錄用于其自身目的,例如從外部源提取文件修訂。這種對工作目錄的無知也允許快速導入非常快速地運行,因為在分支之間切換時不需要執行任何昂貴的文件更新操作。
## 輸入格式
除了原始文件數據(Git不解釋)之外,快速導入輸入格式是基于文本(ASCII)的。這種基于文本的格式簡化了前端程序的開發和調試,特別是在使用更高級別的語言(如Perl,Python或Ruby)時。
快速導入對其輸入非常嚴格。我們在下面說SP,我們的意思是**正好是**一個空格。同樣LF意味著一個(并且只有一個)換行和HT一個(并且只有一個)水平標簽。提供額外的空白字符將導致意外結果,例如名稱中帶有前導或尾隨空格的分支名稱或文件名,或者遇到意外輸入時提前終止快速導入。
### 流評論
為了幫助調試前端,快速導入忽略以`#`(ASCII磅/散列)開頭直到并包括以`LF`結束的行的任何行。注釋行可以包含不包含LF的任何字節序列,因此可以用于包括可能特定于前端的任何詳細調試信息,并且在檢查快速導入數據流時非常有用。
### 日期格式
支持以下日期格式。前端應通過在--date-format =< fmt>中傳遞格式名稱來選擇將用于此導入的格式。命令行選項。
```
raw
```
這是Git原生格式,是`<time> SP <offutc>`。如果未指定--date-format,它也是快速導入的默認格式。
事件的時間由`<time>`指定為自UNIX紀元(午夜,1970年1月1日,UTC)以來的秒數,并寫為ASCII十進制整數。
本地偏移由`<offutc>`指定為UTC的正偏移或負偏移。例如,EST(比UTC晚5小時)將在`<tz>`中用“-0500”表示,而UTC是“+0000”。局部偏移不會影響`<time>`;它僅用作幫助格式化例程顯示時間戳的建議。
如果源材料中沒有本地偏移,請使用“+0000”或最常見的本地偏移。例如,許多組織都有一個CVS存儲庫,該存儲庫只能由位于相同位置和時區的用戶訪問。在這種情況下,可以假設與UTC的合理偏移。
與`rfc2822`格式不同,此格式非常嚴格。格式的任何變化都會導致快速導入以拒絕該值。
```
rfc2822
```
這是RFC 2822描述的標準電子郵件格式。
示例值是“Tue Feb 6 11:22:18 2007 -0500”。 Git解析器是準確的,但在寬松的一面。它是 _git am_ 在應用從電子郵件收到的補丁時使用的解析器。
某些格式錯誤的字符串可能被接受為有效日期。在某些情況下,Git仍然可以從格式錯誤的字符串中獲取正確的日期。還有一些類型的格式錯誤的字符串,Git會解析錯誤,但認為有效。嚴重錯誤的字符串將被拒絕。
與上面的`raw`格式不同,RFC 2822日期字符串中包含的時區/ UTC偏移信息用于在存儲之前將日期值調整為UTC。因此,重要的是這些信息應盡可能準確。
如果源材料使用RFC 2822樣式日期,前端應該讓快速導入處理解析和轉換(而不是嘗試自己做),因為Git解析器已在野外進行了很好的測試。
如果源材料已經使用UNIX-epoch格式,前端應該更喜歡`raw`格式,可以通過哄騙來提供該格式的日期,或者其格式可以輕松轉換為格式,因為解析時沒有歧義。
```
now
```
始終使用當前時間和時區。必須始終為`<when>`提供文字`now`。
這是一種玩具形式。此系統的當前時間和時區始終在通過快速導入創建時復制到標識字符串中。無法指定不同的時間或時區。
提供此特定格式是因為它很難實現,并且可能對想要立即創建新提交的進程有用,而無需使用工作目錄或 _git update-index_ 。
如果在`commit`中使用單獨的`author`和`committer`命令,則時間戳可能不匹配,因為系統時鐘將被輪詢兩次(每個命令一次)。確保作者和提交者身份信息具有相同時間戳的唯一方法是省略`author`(從而從`committer`復制)或使用`now`以外的日期格式。
### 命令
fast-import接受幾個命令來更新當前存儲庫并控制當前導入過程。稍后將對每個命令進行更詳細的討論(帶有示例)。
```
commit
```
通過創建新提交并更新分支以指向新創建的提交來創建新分支或更新現有分支。
```
tag
```
從現有提交或分支創建帶注釋的標記對象。此命令不支持輕量級標記,因為不建議用于記錄有意義的時間點。
```
reset
```
將現有分支(或新分支)重置為特定修訂。必須使用此命令將分支更改為特定修訂,而不對其進行提交。
```
blob
```
將原始文件數據轉換為blob,以備將來在`commit`命令中使用。此命令是可選的,不需要執行導入。
```
checkpoint
```
強制快速導入以關閉當前packfile,生成其唯一的SHA-1校驗和和索引,并啟動新的packfile。此命令是可選的,不需要執行導入。
```
progress
```
導致快速導入以將整行回顯到其自己的標準輸出。此命令是可選的,不需要執行導入。
```
done
```
標記流的結尾。除非使用`--done`命令行選項或`feature done`命令請求`done`功能,否則此命令是可選的。
```
get-mark
```
導致快速導入將對應于標記的SHA-1打印到使用`--cat-blob-fd`設置的文件描述符,或者如果未指定則打印`stdout`。
```
cat-blob
```
導致快速導入將 _cat-file --batch_ 格式的blob打印到使用`--cat-blob-fd`或`stdout`設置的文件描述符(如果未指定)。
```
ls
```
導致快速導入將以 _ls-tree_ 格式描述目錄條目的行打印到使用`--cat-blob-fd`或`stdout`設置的文件描述符(如果未指定)。
```
feature
```
啟用指定的功能。這要求快速導入支持指定的功能,如果不支持則中止。
```
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
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`命令,請求快速導入以保存對新創建的提交的引用,以供將來使用(參見下面的格式)。前端標記它們創建的每個提交是很常見的,從而允許從任何導入的提交創建未來的分支。
`committer`后面的`data`命令必須提供提交消息(參見下面的`data`命令語法)。要導入空提交消息,請使用0長度數據。提交消息是自由格式的,不由Git解釋。目前它們必須以UTF-8編碼,因為快速導入不允許指定其他編碼。
可以包括零個或多個`filemodify`,`filedelete`,`filecopy`,`filerename`,`filedeleteall`和`notemodify`命令以在創建提交之前更新分支的內容。可以按任何順序提供這些命令。但是,建議`filemodify`命令在同一次提交中的所有`filemodify`,`filecopy`,`filerename`和`notemodify`命令之前,因為`filedeleteall`擦除分支清除(見下文)。
命令后的`LF`是可選的(以前是必需的)。
#### `author`
如果作者信息可能與提交者信息不同,則可以選擇顯示`author`命令。如果省略`author`,則fast-import將自動使用提交者作者部分的提交者信息。有關`author`中字段的說明,請參見下文,因為它們與`committer`相同。
#### `committer`
`committer`命令指示誰進行了此提交,以及何時進行此提交。
這里`<name>`是此人的顯示名稱(例如“Com M Itter”),`<email>`是該人的電子郵件地址(“cm@example.com”)。 `LT`和`GT`是文字小于(\ x3c)和大于(\ x3e)的符號。這些是從行中的其他字段分隔電子郵件地址所必需的。注意`<name>`和`<email>`是自由形式的,可以包含任何字節序列,`LT`,`GT`和`LF`除外。 `<name>`通常是UTF-8編碼的。
更改時間由`<when>`使用--date-format =< fmt>選擇的日期格式指定。命令行選項。有關支持的格式集及其語法,請參閱上面的“日期格式”。
#### `from`
`from`命令用于指定從中初始化此分支的提交。此修訂將是新提交的第一個祖先。在此提交時構建的樹的狀態將從`from`提交的狀態開始,并由此提交中的內容修改進行更改。
在第一次提交新分支時省略`from`命令將導致快速導入以創建沒有祖先的提交。這通常僅適用于項目的初始提交。如果前端在創建新分支時從頭開始創建所有文件,則可以使用`merge`命令代替`from`以使用空樹啟動提交。通常需要在現有分支上省略`from`命令,因為該分支上的當前提交被自動假定為新提交的第一個祖先。
由于`LF`在Git refname或SHA-1表達式中無效,因此`<commit-ish>`中不支持引用或轉義語法。
這里`<commit-ish>`是以下任何一種:
* 已存在于fast-import的內部分支表中的現有分支的名稱。如果快速導入不知道名稱,則將其視為SHA-1表達式。
* 標記參考`:<idnum>`,其中`<idnum>`是標記號。
快速導入使用`:`表示標記引用的原因是此字符在Git分支名稱中不合法。前導`:`可以很容易地區分標記42(`:42`)和分支42(`42`或`refs/heads/42`),或簡化的SHA-1,它恰好只包含10位數字。
必須先聲明標記(通過`mark`)才能使用它們。
* 完整的40字節或縮寫提交SHA-1(十六進制)。
* 任何解析為提交的有效Git SHA-1表達式。有關詳細信息,請參閱 [gitrevisions [7]](https://git-scm.com/docs/gitrevisions) 中的“指定修訂”。
* 特殊的空SHA-1(40個零)指定要刪除分支。
從當前分支值重新啟動增量導入的特殊情況應寫為:
```
from refs/heads/branch^0
```
`^0`后綴是必需的,因為快速導入不允許分支從自身開始,并且在從輸入中讀取`from`命令之前在內存中創建分支。添加`^0`將強制快速導入通過Git的修訂解析庫而不是其內部分支表來解析提交,從而加載分支的現有值。
#### `merge`
包括一個額外的祖先提交。附加的祖先鏈接不會更改此提交時構建樹狀態的方式。如果在創建新分支時省略`from`命令,則第一個`merge`提交將是當前提交的第一個祖先,并且分支將從沒有文件開始。快速導入允許每次提交無限數量的`merge`命令,從而建立n路合并。
這里`<commit-ish>`是`from`也接受的任何提交規范表達式(見上文)。
#### `filemodify`
包含在`commit`命令中以添加新文件或更改現有文件的內容。此命令有兩種不同的方法來指定文件的內容。
```
External data format
```
該文件的數據內容已由先前的`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`設置的標記引用。
```
Inline data format
```
尚未提供該文件的數據內容。前端想要將其作為此修改命令的一部分提供。
```
'M' SP <mode> SP 'inline' SP <path> LF
data
```
有關`data`命令的詳細說明,請參見下文。
在兩種格式中,`<mode>`是以八進制指定的文件條目類型。 Git僅支持以下模式:
* `100644`或`644`:普通(不可執行)文件。大多數項目中的大多數文件都使用此模式。如果有疑問,這就是你想要的。
* `100755`或`755`:正常但可執行的文件。
* `120000`:符號鏈接,文件內容將是鏈接目標。
* `160000`:gitlink,對象的SHA-1引用另一個存儲庫中的提交。 Git鏈接只能由SHA或提交標記指定。它們用于實現子模塊。
* `040000`:一個子目錄。子目錄只能由SHA或通過`--import-marks`設置的樹標記指定。
在兩種格式中,`<path>`是要添加的文件的完整路徑(如果尚未存在)或已修改(如果已存在)。
`<path>`字符串必須使用UNIX樣式的目錄分隔符(正斜杠`/`),可以包含`LF`以外的任何字節,并且不能以雙引號(`"`)開頭。
路徑可以使用C風格的字符串引用;這在所有情況下都是可接受的,如果文件名以雙引號開頭或包含`LF`,則是強制性的。在C風格的引用中,完整的名稱應該用雙引號括起來,并且任何`LF`,反斜杠或雙引號字符必須通過在其前面加上反斜杠(例如,`"path/with\n, \\ and \" in it"`)進行轉義。
`<path>`的值必須是規范形式。那不是:
* 包含一個空目錄組件(例如`foo//bar`無效),
* 以目錄分隔符結束(例如`foo/`無效),
* 從目錄分隔符開始(例如`/foo`無效),
* 包含特殊組件`.`或`..`(例如`foo/./bar`和`foo/../bar`無效)。
樹的根可以用空字符串表示為`<path>`。
建議始終使用UTF-8對`<path>`進行編碼。
#### `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`命令立即生效。將源位置重命名為目標后,應用于源位置的任何將來命令都將在其中創建新文件,而不會影響重命名的目標。
請注意,`filerename`與`filecopy`后跟源位置的`filedelete`相同。使用`filerename`有一個輕微的性能優勢,但優勢是如此之小,以至于永遠不值得嘗試將源材料中的刪除/添加對轉換為重命名以進行快速導入。提供此`filerename`命令只是為了簡化已經具有重命名信息的前端,并且不希望將其分解為`filecopy`后跟`filedelete`。
#### `filedeleteall`
包含在`commit`命令中,以從分支中刪除所有文件(以及所有目錄)。此命令重置內部分支結構,使其中沒有文件,允許前端隨后從頭開始添加所有有趣的文件。
```
'deleteall' LF
```
如果前端不知道(或不關心)當前在分支上的文件,并且因此無法生成正確的`filedelete`命令來更新內容,則此命令非常有用。
發出`filedeleteall`后跟所需的`filemodify`命令來設置正確的內容將產生與僅發送所需的`filemodify`和`filedelete`命令相同的結果。然而,`filedeleteall`方法可能需要快速導入,以便為每個活動分支使用稍多的內存(即使是大多數大型項目也不到1 MiB);鼓勵這樣做的前端只能輕松獲取提交的受影響路徑。
#### `notemodify`
包含在`commit` `<notes_ref>`命令中,用于添加注釋`<commit-ish>`的新注釋或更改此注釋內容。在內部,它類似于`<commit-ish>`路徑上的filemodify 100644(可能拆分為子目錄)。除了`filedeleteall`之外,不建議使用任何其他命令寫入`<notes_ref>`樹以刪除此樹中的所有現有注釋。此命令有兩種不同的方法來指定注釋的內容。
```
External data format
```
該注釋的數據內容已由先前的`blob`命令提供。前端只需要將它連接到要注釋的提交。
```
'N' SP <dataref> SP <commit-ish> LF
```
這里`<dataref>`可以是先前`blob`命令設置的標記引用(`:<idnum>`),也可以是現有Git blob對象的完整40字節SHA-1。
```
Inline data format
```
該筆記的數據內容尚未提供。前端想要將其作為此修改命令的一部分提供。
```
'N' SP 'inline' SP <commit-ish> LF
data
```
有關`data`命令的詳細說明,請參見下文。
在兩種格式中,`<commit-ish>`是`from`也接受的任何提交規范表達式(見上文)。
### `mark`
安排快速導入以保存對當前對象的引用,允許前端在未來的某個時間點調用此對象,而不知道它的SHA-1。這里當前對象是`mark`命令出現的對象創建命令。這可以是`commit`,`tag`和`blob`,但`commit`是最常用的用法。
```
'mark' SP ':' <idnum> LF
```
其中`<idnum>`是前端指定給該標記的數字。 `<idnum>`的值表示為ASCII十進制整數。值0保留,不能用作標記。只有大于或等于1的值才可用作標記。
自動創建新標記。只需在另一個`mark`命令中重復使用相同的`<idnum>`,就可以將現有標記移動到另一個對象。
### `original-oid`
提供原始源代碼管理系統中對象的名稱。快速導入將簡單地忽略該指令,但是在進行快速導入之前對進行操作和修改流的過濾進程可能會使用此信息
```
'original-oid' SP <object-identifier> LF
```
其中`<object-identifer>`是任何不包含LF的字符串。
### `tag`
創建引用特定提交的帶注釋標記。要創建輕量級(非注釋)標記,請參閱下面的`reset`命令。
```
'tag' SP <name> LF
'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>`,快速導入會將相應的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標記_進程離線創建這些標記的帶注釋版本。
### `reset`
創建(或重新創建)命名分支,可選擇從特定修訂開始。 reset命令允許前端為現有分支發出新的`from`命令,或者從現有提交創建新分支而不創建新提交。
```
'reset' SP <ref> LF
('from' SP <commit-ish> LF)?
LF?
```
有關`<ref>`和`<commit-ish>`的詳細說明,請參見上文`commit`和`from`。
命令后的`LF`是可選的(以前是必需的)。
`reset`命令也可用于創建輕量級(非注釋)標記。例如:
```
reset refs/tags/938
from :938
```
將創建輕量級標簽`refs/tags/938`引用任何提交標記`:938`引用。
### `blob`
請求將一個文件修訂版寫入packfile。修訂與任何提交無關;必須通過指定標記引用blob,在后續`commit`命令中形成此連接。
```
'blob' LF
mark?
original-oid?
data
```
mark命令在這里是可選的,因為一些前端選擇為它們自己生成blob的Git SHA-1,并直接將其提供給`commit`。然而,這通常比它的價值更多,因為標記的存儲成本低且易于使用。
### `data`
提供原始數據(用作blob /文件內容,提交消息或帶注釋的標記消息)以快速導入。可以使用精確的字節計數提供數據,也可以使用終止線分隔數據。用于生產質量轉換的真正前端應始終使用精確的字節數格式,因為它更強大且性能更好。分隔格式主要用于測試快速導入。
出現在`data`命令的`<raw>`部分中的注釋行始終被視為數據主體的一部分,因此永遠不會被快速導入忽略。這樣可以安全地導入任何行可能以`#`開頭的文件/消息內容。
```
Exact byte count format
```
前端必須指定數據的字節數。
```
'data' SP <count> LF
<raw> LF?
```
其中`<count>`是`<raw>`中出現的確切字節數。 `<count>`的值表示為ASCII十進制整數。 `<raw>`兩側的`LF`不包含在`<count>`中,不會包含在導入的數據中。
`<raw>`之后的`LF`是可選的(以前是必需的),但建議使用。始終包含它會使調試快速導入流更容易,因為下一個命令總是從下一行的第0列開始,即使`<raw>`沒有以`LF`結束。
```
Delimited format
```
分隔符字符串用于標記數據的結尾。 fast-import將通過搜索分隔符來計算長度。此格式主要用于測試,不建議用于實際數據。
```
'data' SP '<<' <delim> LF
<raw> LF
<delim> LF
LF?
```
其中`<delim>`是選定的分隔符字符串。字符串`<delim>`不能在`<raw>`中單獨出現在一行上,否則快速導入會認為數據比實際更早結束。 `LF`立即尾隨`<raw>`是`<raw>`的一部分。這是分隔格式的限制之一,不可能提供沒有LF作為其最后一個字節的數據塊。
`<delim> LF`之后的`LF`是可選的(曾經是必需的)。
### `checkpoint`
強制快速導入以關閉當前的packfile,啟動一個新文件,并保存所有當前的分支引用,標記和標記。
```
'checkpoint' LF
LF?
```
請注意,當前包文件達到--max-pack-size或4 GiB時,快速導入會自動切換packfiles,無論哪個限制較小。在自動packfile開關期間,快速導入不會更新分支引用,標記或標記。
由于`checkpoint`可能需要大量的CPU時間和磁盤IO(要計算整個包SHA-1校驗和,生成相應的索引文件,并更新refs),單個`checkpoint`可能需要幾分鐘命令完成。
前端可能會選擇在極大且長時間運行的導入期間發出檢查點,或者當他們需要允許另一個Git進程訪問分支時。然而,鑒于可以通過快速導入在大約3小時內將30 GiB Subversion存儲庫加載到Git中,可能不需要顯式檢查點。
命令后的`LF`是可選的(以前是必需的)。
### `progress`
當從輸入流處理命令時,導致快速導入將未修改的整個`progress`行打印到其標準輸出通道(文件描述符1)。否則,該命令對當前導入或任何快速導入的內部狀態沒有影響。
```
'progress' SP <any> LF
LF?
```
命令的`<any>`部分可以包含不包含`LF`的任何字節序列。命令后的`LF`是可選的。調用者可能希望通過諸如sed之類的工具處理輸出以刪除行的前導部分,例如:
```
frontend | git fast-import | sed 's/^progress //'
```
在`checkpoint`之后立即放置`progress`命令將在`checkpoint`完成時通知讀者,并且可以安全地訪問快速導入更新的參考。
### `get-mark`
導致快速導入將對應于標記的SHA-1打印到stdout或先前使用`--cat-blob-fd`參數排列的文件描述符。否則該命令對當前導入沒有影響;它的目的是檢索稍后提交可能要在其提交消息中引用的SHA-1。
```
'get-mark' SP ':' <idnum> LF
```
此命令可以在流中接受注釋的任何位置使用。特別是,`get-mark`命令可以在提交過程中使用,但不能在`data`命令的中間使用。
有關如何安全讀取此輸出的詳細信息,請參閱下面的“對命令的響應”。
### `cat-blob`
導致快速導入將blob打印到先前使用`--cat-blob-fd`參數排列的文件描述符。否則該命令對當前導入沒有影響;其主要目的是檢索可能位于快速導入內存但無法從目標存儲庫訪問的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
```
此命令可以在流中接受注釋的任何位置使用。特別是,`cat-blob`命令可以在提交過程中使用,但不能在`data`命令的中間使用。
有關如何安全讀取此輸出的詳細信息,請參閱下面的“對命令的響應”。
### `ls`
在先前使用`--cat-blob-fd`參數排列的文件描述符的路徑上打印有關對象的信息。這允許從活動提交(使用`cat-blob`)打印blob或從先前提交中復制blob或樹以在當前提交中使用(使用`filemodify`)。
`ls`命令可以在流中接受注釋的任何位置使用,包括提交的中間位置。
```
Reading from the active commit
```
此表單只能在`commit`的中間使用。該路徑在fast-import的活動提交中命名目錄條目。在這種情況下必須引用該路徑。
```
'ls' SP <path> LF
```
```
Reading from a named tree
```
`<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`
要求快速導入支持指定的功能,如果不支持,則中止。
```
'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命令行選項會覆蓋流中的任何這些“功能”命令;第三,“功能import-marks-if-exists”就像相應的命令行選項一樣,會以靜默方式跳過不存在的文件。
```
get-mark
```
```
cat-blob
```
```
ls
```
要求后端分別支持 _get-mark_ , _cat-blob_ 或 _ls_ 命令。不支持指定命令的快速導入版本將退出并顯示一條消息。這樣可以使用明確的消息提前導出錯誤,而不是在檢測到不支持的命令之前在導入的早期浪費時間。
```
notes
```
要求后端支持 _commit_ (N)子命令到 _commit_ 命令。快速導入不支持注釋的版本將退出,并顯示一條消息。
```
done
```
如果流沒有_完成_命令結束,則輸出錯誤。如果沒有此功能,導致前端突然在流中方便的位置結束的錯誤可能無法檢測到。例如,如果導入前端在中間操作中死亡而不在其下級git快速導入實例中發出SIGTERM或SIGKILL,則可能發生這種情況。
### `option`
處理指定的選項,以便git fast-import以適合前端需要的方式運行。請注意,前端指定的選項會被用戶指定用于git快速導入的任何選項覆蓋。
```
'option' SP <option> LF
```
命令的`<option>`部分可能包含OPTIONS部分中列出的任何不改變導入語義的選項,沒有前導`--`并且以相同的方式處理。
選項命令必須是輸入上的第一個命令(不計算功能命令),以便在任何非選項命令出錯后給出選項命令。
以下命令行選項更改導入語義,因此不能作為選項傳遞:
* 日期格式
* 進口標志
* 出口標志
* 貓BLOB-FD
* 力
### `done`
如果未使用`done`功能,則將其視為已讀取EOF。這可以用來告訴快速導入提前完成。
如果正在使用`--done`命令行選項或`feature done`命令,則`done`命令是必需的,并標記流的結束。
## 對命令的回應
快速導入寫入的新對象不能立即使用。大多數快速導入命令在下一個檢查點(或完成)之前沒有可見效果。前端可以發送命令來填充快速導入的輸入管道,而不必擔心它們將如何快速生效,從而通過簡化調度來提高性能。
但是,對于某些前端,能夠在更新時從當前存儲庫中讀回數據非常有用(例如,當源材料根據要應用于先前導入的對象的補丁描述對象時)。這可以通過連接前端和通過雙向管道快速導入來實現:
```
mkfifo fast-import-output
frontend <fast-import-output |
git fast-import >fast-import-output
```
以這種方式設置的前端可以使用`progress`,`get-mark`,`ls`和`cat-blob`命令從正在進行的導入中讀取信息。
為避免死鎖,在執行可能阻塞的快速導入寫入之前,此類前端必須完全使用`progress`,`ls`,`get-mark`和`cat-blob`的任何掛起輸出。
## 崩潰報告
如果快速導入提供無效輸入,它將以非零退出狀態終止,并在其導入的Git存儲庫的頂層創建崩潰報告。崩潰報告包含內部快速導入狀態的快照以及導致崩潰的最新命令。
所有最近的命令(包括流注釋,文件更改和進度命令)都顯示在崩潰報告中的命令歷史記錄中,但是從崩潰報告中排除了原始文件數據和提交消息。此排除可以節省報告文件中的空間,并減少快速導入在執行期間必須執行的緩沖量。
編寫崩潰報告后,快速導入將關閉當前的包文件并導出標記表。這允許前端開發人員檢查存儲庫狀態并從崩潰點繼續導入。由于導入未成功完成,因此在崩潰期間不會更新已修改的分支和標記。可以在崩潰報告中找到分支和標記信息,如果需要更新,則必須手動應用。
崩潰示例:
```
$ 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
```
## 技巧和竅門
從快速導入的各種用戶收集了以下提示和技巧,并在此處作為建議提供。
### 每個提交使用一個標記
進行存儲庫轉換時,每次提交使用唯一標記(`mark :<n>`)并在命令行上提供--export-marks選項。 fast-import將轉儲一個文件,該文件列出了每個標記和與之對應的Git對象SHA-1。如果前端可以將標記綁定到源存儲庫,則可以通過將每個Git提交與相應的源修訂進行比較來輕松驗證導入的準確性和完整性。
來自Perforce或Subversion等系統,這應該非常簡單,因為快速導入標記也可以是Perforce變更集編號或Subversion版本號。
### 自由地跳過分支機構
在導入過程中,不要試圖優化前端以一次粘貼到一個分支。盡管快速導入可能會稍快一些,但它往往會大大增加前端代碼的復雜性。
內置于快速導入的分支LRU往往表現得非常好,激活非活動分支的成本非常低,以至于在分支之間反彈幾乎不會影響導入性能。
### 處理重命名
導入重命名的文件或目錄時,只需刪除舊名稱并在相應的提交期間修改新名稱。 Git在事后執行重命名檢測,而不是在提交期間顯式執行。
### 使用標記修復分支
一些其他SCM系統允許用戶從多個文件創建標簽,這些文件不是來自相同的提交/變更集。或者創建標記,這些標記是存儲庫中可用文件的子集。
如果不至少進行一次“修復”文件以匹配標記內容的提交,則無法在Git中導入這些標記。使用fast-import的`reset`命令將正常分支空間之外的虛擬分支重置為標記的基本提交,然后提交一個或多個文件修復提交,最后標記虛擬分支。
例如,因為所有正常分支都以`refs/heads/`名稱存儲在標簽修復分支`TAG_FIXUP`中。這樣,導入器使用的fixup分支就不可能與從源導入的真實分支發生名稱空間沖突(名稱`TAG_FIXUP`不是`refs/heads/TAG_FIXUP`)。
提交修正時,請考慮使用`merge`將提交文件修訂的提交連接到fixup分支。這樣做將允許諸如 _git blame_ 之類的工具跟蹤真實的提交歷史并正確地注釋源文件。
快速導入終止后,前端需要執行`rm .git/TAG_FIXUP`以刪除虛擬分支。
### 立即導入,稍后重新包裝
一旦快速導入完成,Git存儲庫就完全有效并可以使用了。通常這只需要非常短的時間,即使對于相當大的項目(100,000多次提交)也是如此。
但是,重新打包存儲庫對于改善數據位置和訪問性能是必要的。在極大的項目上也可能需要數小時(特別是如果使用-f和大的--window參數)。由于重新打包可以安全地與讀者和作者一起運行,因此在后臺運行重新打包并在完成后完成。沒有理由等待探索你的新Git項目!
如果您選擇等待重新包裝,請不要嘗試運行基準測試或性能測試,直到重新打包完成。快速導入輸出次優的包文件,這些包裝文件在實際使用情況下從未見過。
### 重新包裝歷史數據
如果您要重新打包非常舊的導入數據(例如,比去年更早),請考慮在運行 _git repack_ 時花費一些額外的CPU時間并提供--window = 50(或更高)。這將花費更長的時間,但也會產生更小的packfile。您只需要花費一次精力,使用您的項目的每個人都將從較小的存儲庫中受益。
### 包括一些進度消息
每隔一段時間,您的前端會發出`progress`消息以快速導入。消息的內容完全是自由格式的,因此一個建議是每當當前提交日期進入下個月時輸出當前月份和年份。了解已處理了多少數據流后,您的用戶會感覺更好。
## 包裝優化
打包blob時,fast-import總是試圖對寫入的最后一個blob進行處理。除非前端特別安排,否則這可能不是同一文件的先前版本,因此生成的delta不會是最小的。生成的packfile將被壓縮,但不是最佳的。
有效訪問單個文件的所有修訂版(例如讀取RCS / CVS,v文件)的前端可以選擇將該文件的所有修訂版作為連續`blob`命令序列提供。這允許快速導入以對彼此的不同文件修訂進行分區,從而節省最終packfile中的空間。標記可用于稍后在`commit`命令序列期間識別單個文件修訂。
快速導入創建的packfile不會鼓勵良好的磁盤訪問模式。這是由于快速導入按照標準輸入接收的順序寫入數據引起的,而Git通常在packfiles中組織數據以使最新(當前提示)數據出現在歷史數據之前。 Git還將提交集中在一起,通過更好的緩存局部性加速修訂遍歷。
因此,強烈建議用戶在快速導入完成后使用`git repack -a -d`重新打包存儲庫,允許Git重新組織packfiles以便更快地訪問數據。如果blob增量不是最理想的(參見上文),那么添加`-f`選項以強制重新計算所有增量可以顯著減少最終的包文件大小(30-50%更小可能非常典型)。
## 記憶利用
有許多因素會影響快速導入執行導入所需的內存量。與核心Git的關鍵部分一樣,快速導入使用自己的內存分配器來分攤與malloc相關的任何開銷。實際上,由于使用了大塊分配,快速導入往往會將任何malloc開銷分攤到0。
### 每個對象
fast-import為在此執行中編寫的每個對象維護一個內存中結構。在32位系統上,結構是32字節,在64位系統上,結構是40字節(由于指針大小較大)。在快速導入終止之前,表中的對象不會被釋放。在32位系統上導入200萬個對象將需要大約64 MiB的內存。
對象表實際上是一個鍵入對象名稱的哈希表(唯一的SHA-1)。此存儲配置允許快速導入以重用現有或已寫入的對象,并避免將重復項寫入輸出包文件。重復的blob在導入中非常常見,通常是由于源中的分支合并。
### 每個標記
標記存儲在稀疏數組中,每個標記使用1個指針(4個字節或8個字節,具體取決于指針大小)。雖然數組是稀疏的,但仍然強烈建議使用前端在1和n之間使用標記,其中n是此導入所需的標記總數。
### 每個分支
分支被分類為活動和非活動。兩個類的內存使用量明顯不同。
非活動分支存儲在一個結構中,該結構使用96或120字節(分別為32位或64位系統),以及每個分支的分支名稱長度(通常小于200字節)。快速導入將輕松處理2 MiB內存中多達10,000個非活動分支。
活動分支與非活動分支具有相同的開銷,但也包含最近在該分支上修改的每個樹的副本。如果子樹`include`由于分支變為活動狀態而未被修改,則其內容將不會被加載到內存中,但如果子樹`src`已被提交修改,因為分支變為活動狀態,則其內容將被加載到內存中。
由于活動分支存儲有關該分支上包含的文件的元數據,因此它們的內存存儲大小可以增長到相當大的大小(見下文)。
快速導入基于最近最少使用的簡單算法自動將活動分支移動到非活動狀態。每個`commit`命令都會更新LRU鏈。可以使用--active-branches =在命令行上增加或減少最大活動分支數。
### 每活動樹
樹(aka目錄)在其條目所需的內存之上僅使用12個字節的內存(請參閱下面的“每個活動文件”)。樹的成本實際上是0,因為它的開銷在各個文件條目上攤銷。
### 每個活動文件條目
活動樹中的文件(和指向子樹的指針)每個條目需要52或64個字節(32/64位平臺)。為了節省空間,文件和樹名稱匯集在一個公共字符串表中,允許文件名“Makefile”僅使用16個字節(在包括字符串頭開銷之后),無論它在項目中出現多少次。
活動分支LRU與文件名字符串池和延遲加載子樹相結合,允許快速導入,在非常有限的內存占用(每個活動分支小于2.7 MiB)內有效導入具有2,000多個分支和45,114+文件的項目。
## SIGNALS
將 **SIGUSR1** 發送到 _git fast-import_ 進程會提前結束當前的packfile,模擬`checkpoint`命令。不耐煩的操作員可以使用此工具來查看對象并從正在進行的導入中復制,但代價是增加了一些運行時間和更差的壓縮。
## 也可以看看
[git-fast-export [1]](https://git-scm.com/docs/git-fast-export)
## GIT
部分 [git [1]](https://git-scm.com/docs/git) 套件
- git
- git-config
- git-help
- git-init
- git-clone
- git-add
- git-status
- git-diff
- git-commit
- git-reset
- git-rm
- git-mv
- git-branch
- git-checkout
- git-merge
- git-mergetool
- git-log
- git-stash
- git-tag
- git-worktree
- git-fetch
- git-pull
- git-push
- git-remote
- git-submodule
- git-show
- git-log
- git-shortlog
- git-describe
- git-apply
- git-cherry-pick
- git-rebase
- git-revert
- git-bisect
- git-blame
- git-grep
- gitattributes
- giteveryday
- gitglossary
- githooks
- gitignore
- gitmodules
- gitrevisions
- gittutorial
- gitworkflows
- git-am
- git-format-patch
- git-send-email
- git-request-pull
- git-svn
- git-fast-import
- git-clean
- git-gc
- git-fsck
- git-reflog
- git-filter-branch
- git-instaweb
- git-archive
- git-bundle
- git-daemon
- git-update-server-info
- git-cat-file
- git-check-ignore
- git-checkout-index
- git-commit-tree
- git-count-objects
- git-diff-index
- git-for-each-ref
- git-hash-object
- git-ls-files
- git-merge-base
- git-read-tree
- git-rev-list
- git-rev-parse
- git-show-ref
- git-symbolic-ref
- git-update-index
- git-update-ref
- git-verify-pack
- git-write-tree