日本語 ▾ トピック ▾ 最新バージョン ▾ git-fast-import は 2.45.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 がデルタを作成しようとするブロブの最大サイズをバイト単位で表したもの。デフォルトは 512m (512 MiB) です。一部のインポーターは、メモリが制約されたシステムではこれを下げることを望むかもしれません。

--depth=<n>

ブロブとツリーのデルタ化における最大デルタ深度。デフォルトは 50 です。

--export-pack-edges=<file>

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

--max-pack-size=<n>

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

fastimport.unpackLimit

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

パフォーマンス

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

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

開発コスト

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

並行操作

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

fast-import は、現在アクティブにインポートしているブランチやタグのリファレンスをロックしません。インポート後、リファレンス更新フェーズ中に、fast-import は既存の各ブランチリファレンスをテストし、更新がfast-forward更新になるかどうかを検証します (リファレンスに格納されているコミットが、書き込まれるコミットの新しい履歴に含まれているかどうか)。更新がfast-forward更新でない場合、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 のデフォルトフォーマットでもあります。

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

ローカルオフセットは <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 スタイルの日付を使用している場合、Git パーサは現場で十分にテストされているため、フロントエンドは fast-import に解析と変換を任せるべきです (自分でやろうと試みるのではなく)。

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

now

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

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

この特定のフォーマットが提供されるのは、実装が簡単であり、作業ディレクトリや git update-index を使用することなく、すぐに新しいコミットを作成したいプロセスに役立つ可能性があるためです。

commit で別々の author および committer コマンドが使用された場合、システムクロックが2回 (各コマンドごとに1回) 照会されるため、タイムスタンプが一致しない可能性があります。author と committer の両方の ID 情報が同じタイムスタンプを持つことを保証する唯一の方法は、author を省略する (したがって committer からコピーする) か、now 以外の datetime フォーマットを使用することです。

コマンド

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

commit

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

tag

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

reset

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

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 フォーマットのブロブを --cat-blob-fd で設定されたファイルディスクリプタに、または指定されていない場合は stdout に出力するようにします。

ls

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

feature

指定された機能を有効にします。これにより、fast-import が指定された機能をサポートしていることが必須となり、サポートしていない場合は中断します。

option

ストリームのセマンティクスを変更しない OPTIONS にリストされている任意のオプションを、フロントエンドのニーズに合わせて指定します。このコマンドはオプションであり、インポートを実行するために必須ではありません。

commit

新しいコミットでブランチを作成または更新し、プロジェクトに対する論理的な変更を1つ記録します。

	'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 をインポートする場合、<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 情報が committer 情報と異なる可能性がある場合、オプションで author コマンドを記述できます。author が省略された場合、fast-import は自動的に committer の情報をコミットの author 部分として使用します。author のフィールドは committer と同じであるため、その説明は以下を参照してください。

committer

committer コマンドは、誰がいつこのコミットを行ったかを示します。

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

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

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] の「リビジョンの指定」を参照してください。

  • 特殊なnull 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 ブロブオブジェクトの完全な40バイト SHA-1 である必要があります。<mode>040000` の場合、<dataref> は既存の Git ツリーオブジェクトの完全な40バイト SHA-1 であるか、--import-marks で設定されたマーク参照である必要があります。

インラインデータ形式

ファイルのデータ内容はまだ提供されていません。フロントエンドは、この変更コマンドの一部としてそれを提供したいと考えています。

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

data コマンドの詳細については以下を参照してください。

両方のフォーマットで、<mode> はファイルエントリのタイプであり、8進数で指定されます。Git は以下のモードのみをサポートしています。

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

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

  • 120000: シンボリックリンク。ファイルの内容はリンク先となります。

  • 160000: gitlink。オブジェクトの 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> には NUL を含めることはできません (リテラルでも \000 としてエスケープしても)。<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 コマンドは、名前変更情報をすでに持っており、それを 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 (おそらくサブディレクトリに分割) に似ています。このツリー内の既存のすべてのノートを削除するための filedeleteall を除き、<notes-ref> ツリーに書き込むために他のコマンドを使用することは推奨されません。このコマンドには、ノートの内容を指定するための2つの異なる方法があります。

外部データ形式

ノートのデータ内容は、以前の blob コマンドによってすでに提供されています。フロントエンドはそれを注釈付けされるコミットに接続するだけです。

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

ここで <dataref> は、以前の blob コマンドによって設定されたマーク参照 (:<idnum>) であるか、既存の Git ブロブオブジェクトの完全な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> の詳細な説明については、上記の commitfrom を参照してください。

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

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

reset refs/tags/938
from :938

は、マーク :938 が参照する任意のコミットを参照する軽量タグ refs/tags/938 を作成します。

blob

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

	'blob' LF
	mark?
	original-oid?
	data

ここでのマークコマンドはオプションです。一部のフロントエンドは、ブロブの Git SHA-1 を独自に生成し、それを直接 commit に渡すことを選択しているためです。しかし、マークは保存コストが低く、使いやすいため、通常はそれだけの価値はありません。

data

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

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

正確なバイト数形式

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

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

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

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

区切り形式

区切り文字列はデータの終わりを示すために使用されます。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 チェックサムの計算、対応するインデックスファイルの生成、およびリファレンスの更新) を必要とするため、単一の 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 を標準出力または以前に --cat-blob-fd 引数で設定されたファイルディスクリプタに出力するようにします。このコマンドは、それ以外の場合、現在のインポートに影響を与えません。その目的は、後のコミットがコミットメッセージで参照したい SHA-1 を取得することです。

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

この出力を安全に読み取る方法の詳細については、以下の「コマンドへの応答」を参照してください。

cat-blob

fast-import が、以前に --cat-blob-fd 引数で設定されたファイルディスクリプタにブロブを出力するようにします。このコマンドは、それ以外の場合、現在のインポートに影響を与えません。その主な目的は、fast-import のメモリにはあるが、ターゲットリポジトリからアクセスできないブロブを取得することです。

	'cat-blob' SP <dataref> LF

<dataref> は、以前に設定されたマーク参照 (:<idnum>) であるか、既存の、または書き込み準備ができている Git ブロブの完全な40バイト SHA-1 であることができます。

出力は git cat-file --batch と同じフォーマットを使用します。

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

このコマンドは filemodify ディレクティブが現れる場所で使用でき、コミットの途中で使用できます。インラインディレクティブを使用する filemodify の場合、data ディレクティブの直前に現れることもできます。

この出力を安全に読み取る方法の詳細については、以下の「コマンドへの応答」を参照してください。

ls

以前に --cat-blob-fd 引数で設定されたファイルディスクリプタに、パスにあるオブジェクトに関する情報を出力します。これにより、アクティブなコミットからのブロブの出力 (cat-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> にあるブロブ、ツリー、またはコミットオブジェクトを表し、後の get-markcat-blobfilemodify、または 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」コマンドは1つだけ許可されます。次に、--import-marks= または --import-marks-if-exists コマンドラインオプションは、ストリーム内のこれらの「feature」コマンドのいずれかをオーバーライドします。第三に、「feature import-marks-if-exists」は、対応するコマンドラインオプションと同様に、存在しないファイルを黙ってスキップします。

get-mark
cat-blob
ls

バックエンドがそれぞれ get-markcat-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 の内部状態のスナップショットと、クラッシュに至るまでの最新のコマンドが含まれています。

すべての最近のコマンド (ストリームコメント、ファイル変更、progress コマンドを含む) はクラッシュレポート内のコマンド履歴に表示されますが、生のファイルデータとコミットメッセージはクラッシュレポートから除外されます。この除外により、レポートファイル内のスペースが節約され、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 (Least Recently Used) は非常にうまく機能する傾向があり、非アクティブなブランチをアクティブにするコストは非常に低いため、ブランチ間を行き来してもインポートパフォーマンスにはほとんど影響しません。

リネームの処理

名前変更されたファイルまたはディレクトリをインポートする場合、対応するコミットで単に古い名前を削除し、新しい名前を変更します。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 リポジトリは完全に有効になり、すぐに使用できます。通常、これは非常に短時間で完了し、非常に大規模なプロジェクト (10万以上のコミット) であっても同様です。

ただし、データ局所性とアクセスパフォーマンスを向上させるためには、リポジトリのリパックが必要です。これは非常に大規模なプロジェクトでは数時間かかることもあります (特に -f と大きな --window パラメータが使用されている場合)。リパックは読み取りと書き込みと並行して安全に実行できるため、バックグラウンドでリパックを実行し、完了したら完了させます。新しい Git プロジェクトを探索するのを待つ理由はありません!

リパックが完了するまで待つことを選択した場合、リパックが完了するまではベンチマークやパフォーマンステストを実行しようとしないでください。fast-import は、実際の使用状況では決して見られない最適ではないパックファイルを出力します。

履歴データのリパック

非常に古いインポートデータ (例: 昨年以前のもの) をリパックしている場合、git repack を実行する際に、追加の CPU 時間を費やして --window=50 (またはそれ以上) を指定することを検討してください。これには時間がかかりますが、より小さなパックファイルが生成されます。この労力は一度だけで済み、プロジェクトを使用するすべての人がより小さなリポジトリの恩恵を受けることができます。

進捗メッセージを含める

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

パックファイル最適化

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バイト)を使用します。配列はスパースですが、フロントエンドは依然として1からnまでのマークを使用することを強く推奨されています。ここでnはこのインポートに必要なマークの総数です。

ブランチごと

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

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

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

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

fast-import は、単純なLRU(least-recently-used)アルゴリズムに基づいて、アクティブなブランチを自動的に非アクティブステータスに移動します。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