日本語 ▾ トピック ▾ 最新バージョン ▾ git-fast-import は 2.50.0 で最終更新されました

名前

git-fast-import - 高速なGitデータインポーターのバックエンド

概要

frontend | git fast-import [<options>]

説明

このプログラムは、通常、エンドユーザーが直接実行することを意図していません。ほとんどのエンドユーザーは、特定の種類の外部ソースを解析し、そこに保存されたコンテンツを *git fast-import* に供給する既存のフロントエンドプログラムのいずれかを使用したいと考えています。

fast-import は、標準入力から混合コマンド/データストリームを読み込み、1つ以上のパックファイルを現在のリポジトリに直接書き込みます。標準入力で EOF を受信すると、fast-import は更新されたブランチとタグの参照を書き出し、新しくインポートされたデータで現在のリポジトリを完全に更新します。

fast-import バックエンド自体は、空のリポジトリ (すでに *git init* によって初期化されているもの) にインポートすることも、既存のデータが入力されたリポジトリを増分的に更新することもできます。特定の外部ソースからの増分インポートがサポートされるかどうかは、使用中のフロントエンドプログラムに依存します。

オプション

--force

新しいコミットが古いコミットを含んでいないため、コミットが失われる可能性がある場合でも、変更された既存のブランチの更新を強制します。

--quiet

--stats によって表示される出力を無効にし、fast-import が成功した場合に通常はサイレントになります。ただし、インポートストリームにユーザー出力を表示するためのディレクティブ (例: progress ディレクティブ) がある場合、対応するメッセージは引き続き表示されます。

--stats

fast-import が作成したオブジェクト、それらが格納されたパックファイル、およびこの実行中に fast-import が使用したメモリに関する基本的な統計情報を表示します。この出力の表示は現在デフォルトですが、--quiet で無効にできます。

--allow-unsafe-features

feature または option コマンドを使用することで、多くのコマンドラインオプションを fast-import ストリーム自体の一部として提供できます。ただし、これらのオプションの一部は安全ではありません (例: fast-import がリポジトリ外のファイルシステムにアクセスすることを許可する)。これらのオプションはデフォルトで無効になっていますが、コマンドラインでこのオプションを指定することで許可できます。これは現在、export-marksimport-marks、および import-marks-if-exists の feature コマンドにのみ影響します。

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-blob、および ls クエリへの応答を stdout ではなくファイルディスクリプタ <fd> に書き込みます。これにより、エンドユーザー向けの progress 出力を他の出力から分離できます。

--date-format=<fmt>

フロントエンドが authorcommitter、および tagger コマンド内で fast-import に供給する日付のタイプを指定します。サポートされているフォーマットとその構文の詳細については、以下の「日付フォーマット」を参照してください。

--done

ストリームの終わりに done コマンドがない場合、エラーで終了します。このオプションは、フロントエンドがストリームを書き始める前に終了する原因となるエラーを検出するのに役立つ場合があります。

マークファイルの場所

--export-marks=<file>

完了時に内部マークテーブルを <file> にダンプします。マークは :markid SHA-1 の形式で1行に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>

パックファイルを作成した後、パックファイルのファイル名と、そのパックファイルに書き込まれた各ブランチの最後のコミットをリストするデータ行を <file> に出力します。この情報は、合計オブジェクトセットが 4 GiB のパックファイル制限を超えるプロジェクトをインポートした後に役立つ場合があります。これらのコミットは *git pack-objects* の呼び出し中にエッジポイントとして使用できるためです。

--max-pack-size=<n>

各出力パックファイルの最大サイズ。デフォルトは無制限です。

fastimport.unpackLimit

git-config[1] を参照してください。

パフォーマンス

fast-import の設計により、最小限のメモリ使用量と処理時間で大規模なプロジェクトをインポートできます。フロントエンドが fast-import に追いつき、データストリームを継続的に供給できると仮定すると、10年以上の履歴と100,000以上の個々のコミットを含むプロジェクトのインポート時間は、非常に控えめな (約2,000米ドル) ハードウェアで通常1〜2時間で完了します。

ほとんどのボトルネックは、外部ソースデータアクセス (ソースがリビジョンを十分に速く抽出できない) またはディスク IO (fast-import はディスクがデータを受け入れるのと同じくらい速く書き込む) に現れるようです。ソースデータがターゲットの Git リポジトリとは別のドライブに保存されている場合 (IO の競合が少ないため)、インポートはより高速に実行されます。

開発コスト

fast-import の典型的なフロントエンドは、約200行の Perl/Python/Ruby コードで構成される傾向があります。ほとんどの開発者は、fast-import に初めて触れる場合でも、Git に初めて触れる場合でも、わずか数時間で動作するインポーターを作成できています。ほとんどの変換ツールは使い捨て (一度使用して、二度と見ない) であることを考えると、これは理想的な状況です。

並列操作

*git push* や *git fetch* と同様に、fast-import によって処理されるインポートは、並列の git repack -a -d または git gc の呼び出し、またはその他の Git 操作 (ルーズオブジェクトは fast-import では決して使用されないため、*git prune* を含む) と並行して安全に実行できます。

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 は 正確に 1つのスペースを意味します。同様に、LF は1つの (そして1つだけの) 改行、HT は1つの (そして1つだけの) 水平タブを意味します。追加の空白文字を提供すると、ブランチ名やファイル名の先頭または末尾にスペースが含まれる、または予期しない入力に遭遇したときに fast-import が早期終了するなどの予期しない結果が発生します。

ストリームコメント

フロントエンドのデバッグを支援するため、fast-import は # (ASCII ポンド/ハッシュ) で始まる行を、行末の LF を含めて無視します。コメント行には、LF を含まない任意のバイトシーケンスを含めることができるため、フロントエンドに固有で fast-import データストリームを検査する際に役立つ詳細なデバッグ情報を含めるために使用できます。

日付形式

次の日付形式がサポートされています。フロントエンドは、--date-format=<fmt> コマンドラインオプションで形式名を渡すことにより、このインポートで使用する形式を選択する必要があります。

raw

これは Git のネイティブ形式であり、<time> SP <offutc> です。--date-format が指定されていない場合、fast-import のデフォルト形式でもあります。

イベントの時刻は、UNIX エポック (1970年1月1日 UTC の午前0時) からの秒数として <time> で指定され、ASCII 10進整数として書き込まれます。

ローカルオフセットは、UTC からの正または負のオフセットとして <offutc> で指定されます。例えば、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 スタイルの日付を使用している場合、フロントエンドは Git パーサーが実際の現場で十分にテストされているため、fast-import に解析と変換を処理させるべきです (自分でそれを行おうとするのではなく)。

ソース資料がすでに UNIX エポック形式を使用しているか、その形式で日付を与えるように誘導できる場合、またはその形式に簡単に変換できる場合、解析に曖昧さがないため、フロントエンドは raw 形式を優先すべきです。

now

常に現在の時刻とタイムゾーンを使用します。<when> には常にリテラルの now を指定する必要があります。

これはおもちゃの形式です。このシステムの現在の時刻とタイムゾーンは、fast-import によって ID 文字列が作成される際に常にコピーされます。異なる時刻またはタイムゾーンを指定する方法はありません。

この特定の形式は、実装が短く、作業ディレクトリや *git update-index* を使用せずに、今すぐ新しいコミットを作成したいプロセスに役立つ可能性があるため提供されています。

commit で個別の authorcommitter コマンドが使用されている場合、システムクロックが2回 (各コマンドで1回ずつ) 照会されるため、タイムスタンプが一致しない場合があります。著者とコミッターの両方の ID 情報が同じタイムスタンプを持つことを保証する唯一の方法は、author を省略するか (committer からコピーされるため)、または now 以外の datetime 形式を使用することです。

コマンド

fast-import は、現在のリポジトリを更新し、現在のインポートプロセスを制御するためにいくつかのコマンドを受け入れます。各コマンドの詳細な議論 (例を含む) は後述します。

commit

新しいコミットを作成し、ブランチを新しく作成されたコミットを指すように更新することで、新しいブランチを作成または既存のブランチを更新します。

tag

既存のコミットまたはブランチから注釈付きタグオブジェクトを作成します。軽量タグは、意味のある時点を記録するのには推奨されないため、このコマンドではサポートされていません。

reset

既存のブランチ (または新しいブランチ) を特定の改訂にリセットします。このコマンドは、コミットを作成せずにブランチを特定の改訂に変更するために使用する必要があります。

blob

生ファイルデータを BLOB に変換し、commit コマンドで将来使用します。このコマンドはオプションであり、インポートを実行するために必要ではありません。

alias

新しいオブジェクトを最初に作成せずに、マークが特定のオブジェクトを参照することを記録します。--import-marks を使用し、欠落しているマークを参照すると fast-import が失敗するため、エイリアスは、削除されたコミットを有効な値 (例: 最も近い削除されていない祖先) に設定する方法を提供できます。

checkpoint

fast-import に現在のパックファイルを閉じ、一意の SHA-1 チェックサムとインデックスを生成し、新しいパックファイルを開始するように強制します。このコマンドはオプションであり、インポートを実行するために必要ではありません。

progress

fast-import が行全体を自身の標準出力にエコーするようにします。このコマンドはオプションであり、インポートを実行するために必要ではありません。

done

ストリームの終わりを示します。このコマンドは、done 機能が --done コマンドラインオプションまたは feature done コマンドを使用して要求されていない限り、オプションです。

get-mark

fast-import が、マークに対応する SHA-1 を、--cat-blob-fd で設定されたファイルディスクリプタ、または指定されていない場合は stdout に出力するようにします。

cat-blob

fast-import が、--cat-blob-fd で設定されたファイルディスクリプタ、または指定されていない場合は stdout に、*cat-file --batch* 形式でBLOBを出力するようにします。

ls

fast-import が、--cat-blob-fd で設定されたファイルディスクリプタ、または指定されていない場合は stdout に、*ls-tree* 形式でディレクトリエントリを記述する行を出力するようにします。

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 をインポートする場合、<ref> の値として refs/heads/RELENG-1_0 を使用します。<ref> の値は Git の有効な参照名でなければなりません。LF は Git の参照名では無効なため、ここでは引用符またはエスケープ構文はサポートされていません。

オプションで mark コマンドが現れ、fast-import に新しく作成されたコミットへの参照を保存するよう要求し、フロントエンドが後で利用できるようにします (形式は後述)。フロントエンドが作成するすべてのコミットをマークし、インポートされた任意のコミットから将来のブランチ作成を可能にすることは非常に一般的です。

committer に続く data コマンドはコミットメッセージを供給する必要があります (data コマンドの構文は後述)。空のコミットメッセージをインポートするには、長さ0のデータを使用します。コミットメッセージは自由形式であり、Git によって解釈されません。現在、fast-import は他のエンコーディングを指定することを許可しないため、UTF-8 でエンコードする必要があります。

コミットを作成する前に、ブランチの内容を更新するために、0個以上の filemodifyfiledeletefilecopyfilerenamefiledeleteall、および notemodify コマンドを含めることができます。これらのコマンドは任意の順序で指定できます。ただし、filedeleteall コマンドは、同じコミット内のすべての filemodifyfilecopyfilerename、および notemodify コマンドの前に配置することをお勧めします。filedeleteall はブランチを完全に消去するためです (後述)。

コマンド後の LF はオプションです (以前は必須でした)。後方互換性の理由から、コミットが data コマンドで終わる場合 (つまり、frommergefilemodifyfiledeletefilecopyfilerenamefiledeleteall、または notemodify コマンドがない場合)、コマンドの最後に1つではなく2つの LF コマンドが現れる場合があります。

author

著者情報がコミッター情報と異なる可能性がある場合、オプションで author コマンドが現れることがあります。author が省略された場合、fast-import は自動的にコミッターの情報をコミットの著者部分に使用します。author のフィールドは committer と同一であるため、その説明は後述を参照してください。

committer

committer コマンドは、このコミットを行った人物と日時を示します。

ここで、<name> は人物の表示名 (例: "Com M Itter") であり、<email> は人物の電子メールアドレス ("cm@example.com") です。LT および GT はリテラルの小なり (\x3c) および大なり (\x3e) 記号です。これらは、電子メールアドレスを行内の他のフィールドから区切るために必要です。<name> と <email> は自由形式であり、LTGT、および LF を除く任意のバイトシーケンスを含めることができます。<name> は通常 UTF-8 でエンコードされます。

変更の時刻は、--date-format=<fmt> コマンドラインオプションで選択された日付形式を使用して <when> で指定されます。サポートされている形式とその構文については、上記の「日付形式」を参照してください。

gpgsig

オプションの gpgsig コマンドは、コミットデータを署名する PGP/GPG 署名を含めるために使用されます。

ここで <alg> は、この署名に使用されるハッシュアルゴリズム (sha1 または sha256) を指定します。

これは非常に実験的なものであり、データストリームの形式は将来、互換性の保証なしに変更される可能性があります。

encoding

オプションの encoding コマンドは、コミットメッセージのエンコーディングを示します。ほとんどのコミットは UTF-8 であり、エンコーディングは省略されますが、これにより、最初に再エンコードすることなくコミットメッセージを Git にインポートできます。

from

from コマンドは、このブランチを初期化するコミットを指定するために使用されます。このリビジョンは、新しいコミットの最初の祖先となります。このコミットで構築されたツリーの状態は、from コミットの状態から始まり、このコミットの内容変更によって変更されます。

新しいブランチの最初のコミットで from コマンドを省略すると、fast-import はそのコミットを祖先なしで作成します。これは、プロジェクトの最初のコミットに対してのみ望ましい傾向があります。フロントエンドが新しいブランチを作成する際にすべてのファイルを最初から作成する場合、コミットを空のツリーで開始するために from の代わりに merge コマンドを使用できます。既存のブランチで from コマンドを省略することは通常望ましいです。そのブランチ上の現在のコミットが新しいコミットの最初の祖先であると自動的に仮定されるためです。

LF は Git の参照名または SHA-1 式では無効なため、<commit-ish> 内では引用符またはエスケープ構文はサポートされていません。

ここで <commit-ish> は以下のいずれかです

  • fast-import の内部ブランチテーブルにすでに存在する既存のブランチの名前。fast-import がその名前を知らない場合、SHA-1 式として扱われます。

  • マーク参照、:<idnum>。ここで <idnum> はマーク番号です。

    fast-import がマーク参照を示すために : を使用する理由は、この文字が Git ブランチ名では使用できないためです。先頭の : により、マーク 42 (:42) とブランチ 42 (42 または refs/heads/42)、またはたまたま10進数字のみで構成された短縮 SHA-1 を容易に区別できます。

    マークは、使用する前に (mark を介して) 宣言する必要があります。

  • 完全な40バイトまたは短縮された16進のコミット SHA-1。

  • コミットに解決される有効な Git SHA-1 式。詳細は gitrevisions[7] の「SPECIFYING REVISIONS」を参照してください。

  • 特別なヌル SHA-1 (40個のゼロ) は、ブランチが削除されることを指定します。

現在のブランチ値から増分インポートを再開する特殊なケースは、次のように記述する必要があります。

	from refs/heads/branch^0

^0 接尾辞は必須です。fast-import はブランチがそれ自体から始まることを許可せず、ブランチは from コマンドが入力から読み取られる前にメモリに作成されるためです。^0 を追加すると、fast-import は内部ブランチテーブルではなく Git のリビジョン解析ライブラリを介してコミットを解決し、既存のブランチ値をロードします。

merge

追加の祖先コミットを1つ含めます。追加の祖先リンクは、このコミットでツリーの状態が構築される方法を変更しません。新しいブランチを作成する際に from コマンドが省略された場合、最初の merge コミットが現在のコミットの最初の祖先となり、ブランチはファイルなしで開始されます。fast-import はコミットごとに無制限の merge コマンドを許可しており、これにより n-way マージが確立されます。

ここで <commit-ish> は、from でも受け入れられるコミット指定式のいずれかです (上記を参照)。

filemodify

commit コマンドに含まれ、新しいファイルを追加したり、既存のファイルの内容を変更したりします。このコマンドには、ファイルの内容を指定する2つの異なる方法があります。

外部データ形式

ファイルのデータ内容は、以前の 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 は次のモードのみをサポートします。

  • 100644 または 644: 通常の (実行可能でない) ファイル。ほとんどのプロジェクトのファイルの大半は、このモードを使用します。迷ったら、これを使用してください。

  • 100755 または 755: 通常の、しかし実行可能なファイル。

  • 120000: シンボリックリンク。ファイルの内容はリンクターゲットになります。

  • 160000: Gitリンク。オブジェクトの SHA-1 は別のリポジトリのコミットを参照します。Gitリンクは、SHAまたはコミットマークを介してのみ指定できます。サブモジュールを実装するために使用されます。

  • 040000: サブディレクトリ。サブディレクトリは、SHAまたは --import-marks で設定されたツリーマークを介してのみ指定できます。

どちらの形式でも <path> は、追加されるファイル (まだ存在しない場合) または変更されるファイル (すでに存在する場合) の完全なパスです。

<path> は、引用符なしのバイト列または C スタイルの引用符付き文字列として記述できます。

<path> が二重引用符 (") で始まらない場合、それは引用符なしの文字列であり、エスケープシーケンスなしでリテラルバイトとして解析されます。ただし、ファイル名に LF が含まれる場合、または二重引用符で始まる場合、引用符なしの文字列として表現することはできず、引用符で囲む必要があります。さらに、filecopy または filerename のソース <path> は、SP を含む場合は引用符で囲む必要があります。

<path> が二重引用符 (") で始まる場合、それは C スタイルの引用符付き文字列であり、完全なファイル名が二重引用符のペアで囲まれ、エスケープシーケンスが使用されます。特定の文字はバックスラッシュを前置することでエスケープする必要があります。LF\n、バックスラッシュは \\、二重引用符は \" と記述されます。一部の文字はオプションでエスケープシーケンスで記述できます: ベルは \a、バックスペースは \b、フォームフィードは \f、改行は \n、キャリッジリターンは \r、水平タブは \t、垂直タブは \v。任意のバイトは3桁の8進コード (例: \033) で記述できます。すべてのファイル名は引用符付き文字列として表現できます。

<path> は UNIX スタイルのディレクトリセパレータ (スラッシュ /) を使用し、その値は正規形式でなければなりません。つまり、次の条件を満たしてはなりません。

  • 空のディレクトリコンポーネント (例: foo//bar は無効) を含むこと。

  • ディレクトリセパレータで終わること (例: foo/ は無効)。

  • ディレクトリセパレータで始まること (例: /foo は無効)。

  • 特殊なコンポーネント . または .. (例: foo/./bar および foo/../bar は無効) を含むこと。

ツリーのルートは、<path> として空の文字列で表すことができます。

<path> は、リテラルまたは \000 としてエスケープされた NULL を含めることはできません。<path> は常に UTF-8 を使用してエンコードすることをお勧めします。

filedelete

commit コマンドに含まれ、ファイルまたはディレクトリ全体をブランチから再帰的に削除します。ファイルまたはディレクトリの削除により親ディレクトリが空になった場合、親ディレクトリも自動的に削除されます。これは、最初の空でないディレクトリまたはルートに到達するまでツリーを上方にカスケードします。

	'D' SP <path> LF

ここで <path> は、ブランチから削除されるファイルまたはサブディレクトリの完全なパスです。<path> の詳細な説明は、上記の filemodify を参照してください。

filecopy

既存のファイルまたはサブディレクトリをブランチ内の異なる場所に再帰的にコピーします。既存のファイルまたはディレクトリは存在している必要があります。宛先が存在する場合、ソースからコピーされた内容によって完全に置き換えられます。

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

ここで、最初の <path> はソースの場所であり、2番目の <path> は宛先です。<path> がどのように見えるかの詳細な説明は、上記の filemodify を参照してください。SP を含むソースパスを使用するには、パスを引用符で囲む必要があります。

filecopy コマンドはすぐに有効になります。ソースの場所が宛先にコピーされたら、そのソースの場所に対して将来適用されるコマンドはコピーの宛先に影響しません。

filerename

既存のファイルまたはサブディレクトリをブランチ内の異なる場所に名前変更します。既存のファイルまたはディレクトリは存在している必要があります。宛先が存在する場合、ソースディレクトリによって置き換えられます。

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

ここで、最初の <path> はソースの場所であり、2番目の <path> は宛先です。<path> がどのように見えるかの詳細な説明は、上記の filemodify を参照してください。SP を含むソースパスを使用するには、パスを引用符で囲む必要があります。

filerename コマンドはすぐに有効になります。ソースの場所が宛先に名前変更されると、そのソースの場所に対して将来適用されるコマンドはそこに新しいファイルを作成し、名前変更の宛先に影響を与えません。

filerename は、filecopy の後にソースの場所の filedelete が続くのと同じであることに注意してください。filerename を使用するとわずかなパフォーマンス上の利点がありますが、その利点は非常に小さく、ソース資料の削除/追加ペアを fast-import の名前変更に変換しようとすることに費やす労力は決してありません。この filerename コマンドは、すでに名前変更情報を持っていて、それを filecopyfiledelete に分解する手間をかけたくないフロントエンドを簡素化するために提供されています。

filedeleteall

commit コマンドに含まれ、ブランチからすべてのファイル (およびすべてのディレクトリ) を削除します。このコマンドは、内部ブランチ構造をファイルなしの状態にリセットし、フロントエンドが後で関連するすべてのファイルを最初から追加できるようにします。

	'deleteall' LF

このコマンドは、フロントエンドが現在ブランチ上にあるファイルを認識していない (または認識しようとしない) ため、コンテンツを更新するための適切な filedelete コマンドを生成できない場合に非常に役立ちます。

filedeleteall の後に、正しいコンテンツを設定するために必要な filemodify コマンドを発行すると、必要な filemodify および filedelete コマンドのみを送信した場合と同じ結果が得られます。filedeleteall のアプローチは、アクティブなブランチごとに fast-import がわずかに多くのメモリを使用する可能性があります (ほとんどの大規模プロジェクトでも1 MiB未満)。したがって、コミットの影響を受けるパスのみを簡単に取得できるフロントエンドは、そうすることをお勧めします。

notemodify

commit <notes-ref> コマンドに含まれ、<commit-ish> に注釈を付ける新しいノートを追加したり、この注釈の内容を変更したりします。内部的には、<commit-ish> パス (おそらくサブディレクトリに分割されている) に対する filemodify 100644 と似ています。このツリー内の既存のすべてのノートを削除するための filedeleteall を除き、<notes-ref> ツリーへの書き込みに他のコマンドを使用することはお勧めしません。このコマンドには、ノートの内容を指定する2つの異なる方法があります。

外部データ形式

ノートのデータ内容は、以前の 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 10進整数で表現されます。値 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 をインポートする場合、<name> には RELENG-1_0-FINAL のみを使用し、fast-import は対応する参照を refs/tags/RELENG-1_0-FINAL として書き込みます。

<name> の値は Git の有効な参照名である必要があり、したがってスラッシュを含めることができます。LF は Git の参照名では無効なため、ここでは引用符またはエスケープ構文はサポートされていません。

from コマンドは commit コマンドと同じです。詳細は上記を参照してください。

tagger コマンドは commit 内の committer と同じ形式を使用します。詳細は上記を参照してください。

tagger に続く data コマンドは、注釈付きタグメッセージを供給する必要があります (data コマンドの構文は後述)。空のタグメッセージをインポートするには、長さ0のデータを使用します。タグメッセージは自由形式であり、Git によって解釈されません。現在、fast-import は他のエンコーディングを指定することを許可しないため、UTF-8 でエンコードする必要があります。

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> の詳細な説明は、上記の commit および from を参照してください。

コマンド後の LF はオプションです (以前は必須でした)。

reset コマンドは、軽量 (非注釈付き) タグを作成するためにも使用できます。例:

reset refs/tags/938
from :938

これにより、マーク :938 が参照するコミットを参照する軽量タグ refs/tags/938 が作成されます。

blob

1つのファイルリビジョンをパックファイルに書き込むことを要求します。リビジョンはどのコミットにも接続されていません。この接続は、割り当てられたマークを介してBLOBを参照することにより、後続の commit コマンドで形成する必要があります。

	'blob' LF
	mark?
	original-oid?
	data

ここではマークコマンドはオプションです。一部のフロントエンドは、BLOB の Git SHA-1 を独自に生成し、それを直接 commit に供給することを選択したためです。しかし、マークは保存が安価で使いやすいため、通常はそれだけの労力に見合いません。

data

生データ (BLOB/ファイルコンテンツ、コミットメッセージ、または注釈付きタグメッセージとして使用) を fast-import に供給します。データは正確なバイト数で指定するか、終了行で区切って供給できます。本番品質の変換を目的とした実際のフロントエンドは、より堅牢でパフォーマンスが高いため、常に正確なバイト数形式を使用する必要があります。区切り形式は、主に fast-import のテストを目的としています。

data コマンドの <raw> 部分に現れるコメント行は、常にデータ本文の一部と見なされ、fast-import によって決して無視されません。これにより、行が # で始まるファイル/メッセージコンテンツを安全にインポートできます。

正確なバイト数形式

フロントエンドはデータのバイト数を指定する必要があります。

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

ここで <count><raw> 内に出現する正確なバイト数です。<count> の値は ASCII 10進整数で表現されます。<raw> の両側の LF<count> に含まれず、インポートされるデータにも含まれません。

<raw> の後の LF はオプションです (以前は必須でした) が、推奨されます。常に含めることで、fast-import ストリームのデバッグが容易になります。これは、<raw>LF で終わっていなくても、次のコマンドが常に次の行の0列目から始まるためです。

区切り形式

データの終わりを示すために区切り文字列が使用されます。fast-import は区切り文字を検索して長さを計算します。この形式は主にテストに役立ち、実際のデータには推奨されません。

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

ここで <delim> は選択された区切り文字列です。文字列 <delim><raw> 内で単独で行に現れてはなりません。そうしないと、fast-import はデータが実際よりも早く終わると考えます。<raw> の直後に続く LF<raw> の一部です。これは区切り形式の制限の1つであり、最後のバイトが LF でないデータチャンクを提供することは不可能です。

<delim> LF の後の LF はオプションです (以前は必須でした)。

alias

新しいオブジェクトを最初に作成せずに、マークが特定のオブジェクトを参照することを記録します。

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

<commit-ish> の詳細な説明は、上記の from を参照してください。

checkpoint

fast-import に現在のパックファイルを閉じ、新しいパックファイルを開始し、現在のすべてのブランチ参照、タグ、およびマークを保存するように強制します。

	'checkpoint' LF
	LF?

fast-import は、現在のパックファイルが --max-pack-size または 4 GiB のいずれか小さい方の制限に達すると、自動的にパックファイルを切り替えることに注意してください。自動パックファイル切り替え中に、fast-import はブランチ参照、タグ、またはマークを更新しません。

checkpoint はかなりの CPU 時間とディスク IO (全体のパック SHA-1 チェックサムの計算、対応するインデックスファイルの生成、および参照の更新のため) を必要とする可能性があるため、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 が、以前に --cat-blob-fd 引数で設定されたファイルディスクリプタに BLOB を出力するようにします。このコマンドは、現在のインポートには影響しません。その主な目的は、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、ツリー、またはコミットオブジェクトを表し、その後の *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 と同様ですが、2つの点で異なります。まず、ストリームごとに1つの "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) サブコマンドをサポートすることを要求します。ノートをサポートしないバージョンの fast-import は、その旨を示すメッセージとともに終了します。

done

ストリームが *done* コマンドなしで終了した場合、エラーを発生させます。この機能がない場合、ストリームの都合の良い時点でフロントエンドが突然終了する原因となるエラーが検出されない可能性があります。これは、例えば、インポートフロントエンドが、下位の git fast-import インスタンスに SIGTERM または SIGKILL を発行せずに、操作の途中で終了した場合などに発生する可能性があります。

option

指定されたオプションを処理し、git fast-import がフロントエンドのニーズに合うように動作させます。フロントエンドによって指定されたオプションは、ユーザーが git fast-import 自体に指定するオプションによって上書きされることに注意してください。

    'option' SP <option> LF

コマンドの <option> 部分には、OPTIONS セクションにリストされているインポートセマンティクスを変更しないオプションのいずれかを含めることができます。-- は先頭に付けずに、同様に扱われます。

オプションコマンドは、入力の最初のコマンドである必要があります (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-markls、および cat-blob コマンドを使用して、進行中のインポートから情報を読み取ることができます。

デッドロックを回避するために、そのようなフロントエンドは、ブロックする可能性のある fast-import への書き込みを実行する前に、progresslsget-mark、および cat-blob からの保留中の出力を完全に消費する必要があります。

クラッシュレポート

fast-import に無効な入力が与えられた場合、非ゼロの終了ステータスで終了し、インポート先の Git リポジトリのトップレベルにクラッシュレポートを作成します。クラッシュレポートには、fast-import の内部状態のスナップショットと、クラッシュにつながった最新のコマンドが含まれます。

最近のすべてのコマンド (ストリームコメント、ファイル変更、進捗コマンドを含む) はクラッシュレポート内のコマンド履歴に表示されますが、生ファイルデータとコミットメッセージはクラッシュレポートから除外されます。この除外により、レポートファイル内のスペースが節約され、fast-import が実行中に実行する必要があるバッファリングの量が削減されます。

クラッシュレポートの書き込み後、fast-import は現在のパックファイルを閉じ、マークテーブルをエクスポートします。これにより、フロントエンド開発者はリポジトリの状態を検査し、クラッシュした時点からインポートを再開できます。インポートが正常に完了しなかったため、変更されたブランチとタグはクラッシュ中に更新されません。ブランチとタグの情報はクラッシュレポートに記載されており、更新が必要な場合は手動で適用する必要があります。

クラッシュの例

$ 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 のさまざまなユーザーから収集されたものであり、提案としてここに提供されています。

コミットごとに1つのマークを使用する

リポジトリ変換を行う際は、コミットごとに一意のマーク (mark :<n>) を使用し、コマンドラインで --export-marks オプションを指定します。fast-import は、すべてのマークとそれに対応する Git オブジェクト SHA-1 をリストしたファイルをダンプします。フロントエンドがマークをソースリポジトリに紐付けることができれば、各 Git コミットと対応するソースリビジョンを比較することで、インポートの正確性と完全性を容易に検証できます。

Perforce や Subversion のようなシステムからの場合、fast-import マークを Perforce チェンジセット番号または Subversion リビジョン番号にすることもできるため、これはかなり簡単です。

ブランチ間を自由に移動する

インポート中にフロントエンドを一度に1つのブランチに限定するよう最適化しようとしない。そうすると fast-import がわずかに高速になるかもしれませんが、フロントエンドコードの複雑性が大幅に増す傾向があります。

fast-import に組み込まれているブランチ LRU は非常にうまく機能する傾向があり、非アクティブなブランチをアクティブ化するコストは非常に低いため、ブランチ間を行き来してもインポートパフォーマンスに実質的に影響はありません。

名前変更の処理

名前変更されたファイルやディレクトリをインポートする場合、対応するコミット中に古い名前を削除し、新しい名前を変更するだけで済みます。Git は、コミット中に明示的にではなく、事後に名前変更を検出します。

タグ修正ブランチの使用

他の SCM システムでは、ユーザーが同じコミット/チェンジセットではない複数のファイルからタグを作成したり、リポジトリで利用可能なファイルの一部であるタグを作成したりできます。

Git でこれらのタグをそのままインポートすることは、タグの内容と一致するようにファイルを「修正」するコミットを少なくとも1つ作成しない限り不可能です。fast-import の reset コマンドを使用して、通常のブランチ空間外のダミーブランチをタグのベースコミットにリセットし、1つ以上のファイル修正コミットを行い、最後にダミーブランチにタグを付けます。

例えば、通常のすべてのブランチが 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(またはそれ以上)を指定することを検討してください。これは時間がかかりますが、より小さなパックファイルを作成します。この努力は一度だけで済み、プロジェクトを使用するすべての人がより小さなリポジトリの恩恵を受けます。

進行状況メッセージを含める

時折、フロントエンドで progress メッセージをfast-importに出力してください。メッセージの内容は完全に自由形式なので、現在のコミット日付が次の月に移動するたびに、現在の月と年を出力することをお勧めします。ユーザーは、データストリームのどのくらいが処理されたかを知ることで、より安心感を得られます。

パックファイルの最適化

ブロブをパックする際、fast-importは常に最後に書き込まれたブロブに対してデルタ化を試みます。フロントエンドによって特に手配されていない限り、これはおそらく同じファイルの以前のバージョンではないため、生成されるデルタは可能な限り最小にはなりません。結果として得られるパックファイルは圧縮されますが、最適ではありません。

単一のファイルのすべてのリビジョンに効率的にアクセスできるフロントエンド(たとえば、RCS/CVSの .v ファイルを読み取る場合)は、そのファイルのすべてのリビジョンを一連の連続した blob コマンドとして提供することを選択できます。これにより、fast-importは異なるファイルリビジョンを相互にデルタ化し、最終的なパックファイルのスペースを節約できます。マークは、一連の commit コマンド中に個々のファイルリビジョンを後で識別するために使用できます。

fast-importによって作成されたパックファイルは、良好なディスクアクセスパターンを促しません。これは、fast-importが標準入力で受信した順序でデータを書き込むのに対し、Gitは通常、パックファイル内のデータを、最新の(現在の先端の)データが履歴データの前に現れるように整理するためです。Gitはまた、コミットをクラスター化し、より良いキャッシュ局所性によってリビジョン遍歴を高速化します。

このため、fast-importが完了した後、ユーザーは git repack -a -d でリポジトリを再パックし、Gitがより高速なデータアクセスのためにパックファイルを再編成することを強く推奨します。ブロブデルタが最適でない場合(上記参照)、すべてのデルタの再計算を強制する -f オプションも追加すると、最終的なパックファイルサイズを大幅に削減できます(30-50%の削減はかなり一般的です)。

git repack を実行する代わりに、git gc --aggressive を実行することもできます。これは、インポート後に他のものも最適化します(例:ルーズ参照のパック)。git-gc[1] の「AGGRESSIVE」セクションで述べられているように、--aggressive オプションは、git-repack[1]-f オプションで新しいデルタを見つけます。上記の理由から、fast-importの後に --aggressive を使用することは、それが価値があることが知られている数少ないケースの1つです。

メモリ使用量

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は既存または既に書き込まれたオブジェクトを再利用し、出力パックファイルへの重複書き込みを避けることができます。重複ブロブはインポートで驚くほど一般的であり、通常はソースのブランチマージが原因です。

マークごと

マークは疎な配列に保存され、マークごとに1つのポインタ(ポインタサイズに応じて4バイトまたは8バイト)を使用します。配列は疎ですが、フロントエンドは依然として、このインポートに必要なマークの総数をnとした場合、1からnまでのマークを使用することを強く推奨します。

ブランチごと

ブランチはアクティブと非アクティブに分類されます。2つのクラスのメモリ使用量は大きく異なります。

非アクティブなブランチは、96バイトまたは120バイト(それぞれ32ビットまたは64ビットシステム)、およびブランチ名の長さ(通常200バイト未満)を使用する構造に、ブランチごとに保存されます。fast-importは、2 MiB未満のメモリで10,000個もの非アクティブなブランチを容易に処理します。

アクティブなブランチは、非アクティブなブランチと同じオーバーヘッドを持ちますが、そのブランチで最近変更されたすべてのツリーのコピーも含まれます。サブツリー include がブランチがアクティブになってから変更されていない場合、その内容はメモリにロードされませんが、サブツリー src がブランチがアクティブになってからコミットによって変更された場合、その内容はメモリにロードされます。

アクティブなブランチは、そのブランチに含まれるファイルのメタデータを格納するため、インメモリのストレージサイズはかなりの大きさになることがあります(下記参照)。

fast-importは、単純な最近使用頻度の低いアルゴリズムに基づいて、アクティブなブランチを非アクティブなステータスに自動的に移動します。LRUチェーンは、各 commit コマンドで更新されます。アクティブなブランチの最大数は、コマンドラインで --active-branches= で増減できます。

アクティブなツリーごと

ツリー(ディレクトリとも呼ばれる)は、そのエントリに必要なメモリ(下記の「アクティブなファイルエントリごと」を参照)に加えて、わずか12バイトのメモリを使用します。ツリーのコストは実質的に0であり、そのオーバーヘッドは個々のファイルエントリに償却されます。

アクティブなファイルエントリごと

アクティブなツリー内のファイル(およびサブツリーへのポインタ)は、エントリごとに52バイトまたは64バイト(32/64ビットプラットフォーム)を必要とします。スペースを節約するために、ファイル名とツリー名は共通の文字列テーブルにプールされ、「Makefile」というファイル名は、プロジェクト内で何回出現しても(文字列ヘッダーのオーバーヘッドを含めて)わずか16バイトを使用します。

アクティブなブランチのLRUは、ファイル名の文字列プールとサブツリーの遅延ロードと組み合わせることで、fast-importが2,000以上のブランチと45,114以上のファイルを持つプロジェクトを非常に限られたメモリフットプリント(アクティブなブランチあたり2.7 MiB未満)で効率的にインポートすることを可能にします。

シグナル

git fast-import プロセスに SIGUSR1 を送信すると、現在のパックファイルが早期に終了し、checkpoint コマンドをシミュレートします。せっかちなオペレータは、この機能を使用して、インポート中のオブジェクトと参照を覗き見ることができますが、その代償として実行時間の増加と圧縮率の悪化が生じます。

設定

このセクションのこの行より下のすべての内容は、git-config[1] ドキュメントから選択的に含まれています。内容はそちらで見られるものと同じです。

fastimport.unpackLimit

git-fast-import[1] によってインポートされたオブジェクトの数がこの制限を下回る場合、オブジェクトはルーズオブジェクトファイルに展開されます。しかし、インポートされたオブジェクトの数がこの制限以上の場合、パックはパックとして保存されます。fast-importからのパックを保存すると、特に遅いファイルシステムでは、インポート操作がより速く完了する可能性があります。設定されていない場合、代わりに transfer.unpackLimit の値が使用されます。

関連項目

GIT

git[1]スイートの一部

scroll-to-top