Git
日本語 ▾ トピック ▾ 最新バージョン ▾ 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フィーチャコマンドにのみ影響します。

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行ずつ書き込まれます。フロントエンドはこのファイルを使用して、インポートが完了した後に検証したり、増分実行でマークテーブルを保存したりできます。<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

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

パフォーマンス

fast-import の設計により、最小限のメモリ使用量と処理時間で大規模なプロジェクトをインポートできます。フロントエンドが fast-import に遅れることなく、継続的にデータを供給できると仮定すると、10 年以上の履歴と 100,000 件以上の個別のコミットを含むプロジェクトのインポートは、一般的に、ごく控えめな (~2,000 米ドル) ハードウェアでわずか 1 ~ 2 時間で完了します。

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

開発コスト

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

並列操作

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

fast-import は、アクティブにインポートしているブランチまたはタグ参照をロックしません。インポート後、参照更新フェーズで、fast-import は各既存のブランチ参照をテストし、更新が高速フォワード更新 (参照に格納されているコミットが、書き込まれるコミットの新しい履歴に含まれている) であることを確認します。更新が高速フォワード更新でない場合、fast-import はその参照の更新をスキップし、代わりに警告メッセージを出力します。fast-import は常にすべてのブランチ参照の更新を試み、最初の失敗で停止することはありません。

ブランチの更新は --force で強制できますが、これは他の点では静かなリポジトリでのみ使用することをお勧めします。--force の使用は、空のリポジトリへの最初のインポートには必要ありません。

技術的な議論

fast-import は、メモリ内の一連のブランチを追跡します。入力ストリームで commit コマンドを送信することにより、インポートプロセス中に任意の時点でブランチを作成または変更できます。この設計により、フロントエンドプログラムは無制限の数のブランチを同時に処理でき、ソースデータから利用可能な順序でコミットを生成できます。また、フロントエンドプログラムを大幅に簡素化します。

fast-import は、現在の作業ディレクトリまたはその中のファイルを使用または変更しません。(ただし、GIT_DIR で参照される現在の Git リポジトリは更新します。)したがって、インポートフロントエンドは、外部ソースからファイルリビジョンを抽出するなど、独自の目的で作業ディレクトリを使用できます。また、この作業ディレクトリの無視により、ブランチを切り替えるときにコストのかかるファイル更新操作を実行する必要がないため、fast-import は非常に高速に実行できます。

入力形式

raw ファイルデータ (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 日午前 0 時、UTC) からの秒数として <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 スタイルの日付を使用している場合、フロントエンドは、(自分で変換を試みるのではなく) fast-import に解析と変換を処理させる必要があります。これは、Git パーサーが実際に十分にテストされているためです。

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

now

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

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

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

commit で個別の author および committer コマンドが使用されている場合、システムのクロックが 2 回 (各コマンドで 1 回) ポーリングされるため、タイムスタンプが一致しない場合があります。作成者とコミッターの両方の ID 情報に同じタイムスタンプを設定することを保証する唯一の方法は、author を省略する (したがって committer からコピーする) か、now 以外の形式を使用することです。

コマンド

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

commit

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

tag

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

reset

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

blob

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

alias

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

checkpoint

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

progress

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

done

ストリームの終了をマークします。このコマンドは、--done コマンドラインオプションまたは feature done コマンドを使用して done 機能が要求された場合を除き、オプションです。

get-mark

fast-import に、--cat-blob-fd で設定されたファイル記述子、または指定されていない場合は stdout に、マークに対応する SHA-1 を出力させます。

cat-blob

fast-import に、cat-file --batch 形式で blob を --cat-blob-fd で設定されたファイル記述子、または指定されていない場合は stdout に出力させます。

ls

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

feature

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

option

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

commit

新しいコミットでブランチを作成または更新し、プロジェクトへの論理的な変更を 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 の有効な refname である必要があります。Git の refname では LF が無効であるため、ここでは引用符やエスケープ構文はサポートされていません。

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

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

0 個以上の filemodifyfiledeletefilecopyfilerenamefiledeleteallnotemodify コマンドを含めて、コミットを作成する前にブランチの内容を更新できます。これらのコマンドは任意の順序で指定できます。ただし、同じコミット内で filedeleteall コマンドの後にすべての filemodifyfilecopyfilerenamenotemodify コマンドを続けることをお勧めします。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”) です。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 コマンドを省略するのは通常望ましいことです。そのブランチの現在のコミットが、新しいコミットの最初の上位コミットであると自動的に想定されるためです。

Git の refname または SHA-1 式では LF が無効であるため、<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 を介して) 宣言する必要があります。

  • 16 進数での完全な 40 バイトまたは省略形のコミット SHA-1。

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

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

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

	from refs/heads/branch^0

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

merge

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

ここで、<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 tree オブジェクトの完全な 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/./barfoo/../bar は無効)。

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

<path> は、リテラルまたは \000 としてエスケープされた NUL を含めることはできません。<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を使用するとわずかなパフォーマンス上の利点がありますが、その利点は非常に小さいため、高速インポートのためにソースマテリアルのdelete/addペアをrenameに変換しようとする価値は決してありません。このfilerenameコマンドは、すでにrename情報を持っているフロントエンドが、filecopyの後にfiledeleteを実行するという分解を面倒に思う必要がないように、簡略化するために提供されています。

filedeleteall

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

	'deleteall' LF

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

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

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のいずれかになります。

インラインデータ形式

ノートのデータコンテンツはまだ提供されていません。フロントエンドは、このmodifyコマンドの一部として提供したいと考えています。

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

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

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

mark

高速インポートに現在のオブジェクトへの参照を保存させ、フロントエンドがそのSHA-1を知らなくても、将来のある時点でこのオブジェクトを呼び出すことができるようにします。ここで、現在のオブジェクトは、markコマンドが表示されるオブジェクト作成コマンドです。これは、committag、およびblobにできますが、commitが最も一般的な使用法です。

	'mark' SP ':' <idnum> LF

ここで、<idnum>は、フロントエンドによってこのマークに割り当てられた番号です。<idnum>の値は、ASCII 10進整数として表されます。値0は予約されており、マークとして使用することはできません。1以上の値のみをマークとして使用できます。

新しいマークは自動的に作成されます。既存のマークは、別のmarkコマンドで同じ<idnum>を再利用するだけで、別のオブジェクトに移動できます。

original-oid

元のソース管理システムでのオブジェクトの名前を提供します。高速インポートはこのディレクティブを単に無視しますが、高速インポートにフィードする前にストリームを操作および変更するフィルター処理プロセスでは、この情報を使用する場合があります。

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

ここで、<object-identifier>はLFを含まない任意の文字列です。

tag

特定のコミットを参照する注釈付きタグを作成します。軽量(非注釈付き)タグを作成するには、以下のresetコマンドを参照してください。

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

ここで、<name>は作成するタグの名前です。

タグ名はGitに保存されるときに自動的にrefs/tags/がプレフィックスとして付けられるため、CVSブランチシンボルRELENG-1_0-FINALをインポートする場合は、<name>RELENG-1_0-FINALのみを使用し、高速インポートは対応する参照をrefs/tags/RELENG-1_0-FINALとして書き込みます。

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

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

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

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

高速インポート内からのインポート中の注釈付きタグへの署名はサポートされていません。独自のPGP/GPG署名を含めようとすることはお勧めできません。フロントエンドは、通常そのような署名に使用される完全なバイトセットに(簡単には)アクセスできないためです。署名が必要な場合は、高速インポート内からresetを使用して軽量タグを作成し、標準のgit tagプロセスを使用してそれらのタグの注釈付きバージョンをオフラインで作成します。

reset

指定されたリビジョンから開始することもできる、名前付きブランチを作成(または再作成)します。resetコマンドを使用すると、フロントエンドが既存のブランチに対して新しいfromコマンドを発行したり、新しいコミットを作成せずに既存のコミットから新しいブランチを作成したりできます。

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

<ref><commit-ish>の詳細については、上記のcommitおよびfromを参照してください。

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

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

reset refs/tags/938
from :938

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

blob

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

	'blob' LF
	mark?
	original-oid?
	data

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

data

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

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

正確なバイト数形式

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

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

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

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

区切り形式

区切り文字文字列は、データの終わりをマークするために使用されます。高速インポートは、区切り文字を検索して長さを計算します。この形式は、主にテストに役立ち、実際のデータには推奨されません。

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

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

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

alias

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

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

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

checkpoint

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

	'checkpoint' LF
	LF?

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

checkpointにはかなりのCPU時間とディスクIO(パック全体のSHA-1チェックサムの計算、対応するインデックスファイルの生成、および参照の更新)が必要になる可能性があるため、1つのcheckpointコマンドの完了に数分かかることがあります。

フロントエンドは、非常に大規模で長期間実行されるインポート中、または別のGitプロセスがブランチにアクセスできるようにする必要がある場合に、チェックポイントを発行することを選択できます。ただし、30GiBのSubversionリポジトリを高速インポートを介して約3時間でGitにロードできることを考えると、明示的なチェックポイントは必要ない場合があります。

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

progress

コマンドが入力ストリームから処理されるときに、高速インポートが変更されていないprogress行全体を標準出力チャネル(ファイル記述子1)に出力するようにします。それ以外の場合、コマンドは現在のインポートにも、高速インポートの内部状態にも影響しません。

	'progress' SP <any> LF
	LF?

コマンドの <any> 部分には、LF を含まない任意のバイト列を含めることができます。コマンド後の LF はオプションです。呼び出し元は、行の先頭部分を削除するために、sed などのツールで出力を処理することができます。例えば、以下のように使用します。

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

checkpoint の直後に progress コマンドを置くと、checkpoint が完了し、fast-import が更新した参照に安全にアクセスできるタイミングをリーダーに通知できます。

get-mark

fast-import に、マークに対応する SHA-1 を stdout または --cat-blob-fd 引数で事前に指定されたファイルディスクリプタに出力させます。このコマンドは、現在のインポートには影響を与えません。その目的は、後のコミットでコミットメッセージ内で参照する可能性のある SHA-1 を取得することです。

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

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

cat-blob

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

	'cat-blob' SP <dataref> LF

<dataref> には、以前に設定されたマーク参照 (:<idnum>) または、既存の、または書き込み準備ができた Git blob の完全な 40 バイトの SHA-1 を指定できます。

出力は git cat-file --batch と同じ形式を使用します。

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

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

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

ls

--cat-blob-fd 引数で事前に指定されたファイルディスクリプタに、パスにあるオブジェクトに関する情報を出力します。これにより、アクティブなコミットから blob を出力 (cat-blob を使用) したり、前のコミットから blob またはツリーをコピーして現在のコミットで使用 (filemodify を使用) したりできます。

ls コマンドは、filemodify ディレクティブを使用できる場所で使用でき、コミットの途中で使用できます。

アクティブなコミットからの読み取り

この形式は、commit の途中でのみ使用できます。パスは、fast-import のアクティブなコミット内のディレクトリ エントリを示します。この場合、パスは引用符で囲む必要があります。

	'ls' SP <path> LF
名前付きツリーからの読み取り

<dataref> には、マーク参照 (:<idnum>) または、既存の、または書き込み準備ができた Git タグ、コミット、またはツリーオブジェクトの完全な 40 バイトの SHA-1 を指定できます。パスは、<dataref> で指定されたツリーのトップレベルからの相対パスです。

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

<path> の詳細については、上記の filemodify を参照してください。

出力は git ls-tree <tree> -- <path> と同じ形式を使用します。

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

<dataref> は、<path> にある blob、ツリー、またはコミットオブジェクトを表し、後続の *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" コマンドは 1 つしか許可されないことです。2 つ目は、--import-marks= または --import-marks-if-exists コマンドラインオプションは、ストリーム内のこれらの "feature" コマンドをすべてオーバーライドすることです。3 つ目は、"feature import-marks-if-exists" は、対応するコマンドラインオプションと同様に、存在しないファイルをサイレントにスキップすることです。

get-mark
cat-blob
ls

それぞれ、バックエンドが *get-mark*、*cat-blob*、または *ls* コマンドをサポートすることを要求します。指定されたコマンドをサポートしていない fast-import のバージョンは、それを示すメッセージとともに終了します。これにより、サポートされていないコマンドが検出される前に、インポートの初期段階で時間を無駄にするのではなく、明確なメッセージでインポートを早期にエラーにすることができます。

notes

バックエンドが *commit* コマンドに対する *notemodify* (N) サブコマンドをサポートすることを要求します。notes をサポートしていない fast-import のバージョンは、それを示すメッセージとともに終了します。

done

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

option

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

    'option' SP <option> LF

コマンドの <option> 部分には、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 に無効な入力が供給された場合、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 は、実際には決して見られない最適でないパックファイルを出力します。

履歴データのリパック

非常に古いインポートデータ(例:過去 1 年よりも古いデータ)をリパックする場合は、余分な CPU 時間を費やし、*git repack* を実行するときに --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 を実行することもできます。これにより、インポート後の他のことも最適化されます(例:ルーズな ref をパックするなど)。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.7 MiB 未満)で、2,000 以上のブランチと 45,114 以上のファイルを含むプロジェクトを効率的にインポートできます。

シグナル

git fast-import プロセスに SIGUSR1 を送信すると、現在のパックファイルが早期に終了し、checkpoint コマンドがシミュレートされます。せっかちなオペレーターは、この機能を使用して、実行時間と圧縮率の低下を犠牲にして、進行中のインポートからオブジェクトと ref をのぞき見ることができます。

構成

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

fastimport.unpackLimit

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

関連項目

GIT

git[1] スイートの一部

scroll-to-top