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

名前

git-sparse-checkout - 作業ツリーを追跡ファイルのサブセットに削減する

概要

git sparse-checkout (init | list | set | add | reapply | disable | check-rules) [<options>]

説明

このコマンドは、スパースチェックアウトを作成するために使用されます。これにより、作業ツリー内のすべての追跡ファイルを一部のファイルのみに限定することができます。また、存在するファイルのサブセットを切り替えたり、元に戻して作業コピー内にすべての追跡ファイルが存在する状態に戻したりすることも可能です。

ファイルのサブセットは、コーンモード(デフォルト)でディレクトリのリストを提供するか、非コーンモードでパターンのリストを提供することによって選択されます。

スパースチェックアウト中では、他の Git コマンドの動作が少し異なります。例えば、ブランチを切り替えても、スパースチェックアウトのディレクトリ/パターンの外部のパスは更新されず、git commit -a は、スパースチェックアウトのディレクトリ/パターンの外部のパスを削除として記録しません。

このコマンドは実験的です。その動作、およびスパースチェックアウトが存在する場合の他のコマンドの動作は、将来変更される可能性があります。

コマンド

list

スパースチェックアウトファイル内のディレクトリまたはパターンを記述します。

set

必要なスパースチェックアウト設定(core.sparseCheckoutcore.sparseCheckoutCone、および index.sparse)がまだ目的の値に設定されていない場合、これらを有効にし、set サブコマンドに続く引数のリストからスパースチェックアウトファイルを投入し、作業ディレクトリを一致するように更新します。

作業ツリー内のスパースチェックアウト設定を調整しても、他の作業ツリーのスパースチェックアウト設定が変更されないように、set サブコマンドは、まだ存在しない場合はリポジトリ設定を作業ツリー固有の設定を使用するようにアップグレードします。set サブコマンドの引数で定義されたスパース性は、作業ツリー固有のスパースチェックアウトファイルに保存されます。詳細については、git-worktree[1] および git-config[1]extensions.worktreeConfig のドキュメントを参照してください。

--stdin オプションが指定された場合、ディレクトリまたはパターンは引数からではなく、標準入力から改行区切りのリストとして読み取られます。

デフォルトでは、入力リストはディレクトリのリストと見なされ、git ls-tree -d --name-only の出力と一致します。これには、二重引用符 (") で始まるパス名を C スタイルの引用文字列として解釈することも含まれます。指定されたディレクトリ(任意の深さ)内のすべてのファイルは、指定されたディレクトリまたはその祖先のいずれかの兄弟であるファイルと同様に、スパースチェックアウトに含まれることに注意してください(詳細については、以下のCONE PATTERN SETを参照してください)。以前は、これがデフォルトではなく、--cone を指定するか、core.sparseCheckoutCone を有効にする必要がありました。

--no-cone が渡された場合、入力リストはパターンのリストと見なされます。このモードには、--sparse-index のような一部のオプションと機能しないなど、いくつかの欠点があります。以下の「非コーンモードの問題」セクションで説明されているように、このモードを使用することはお勧めしません。

--[no-]sparse-index オプションを使用して、スパースインデックスを使用します(デフォルトは使用しません)。スパースインデックスは、スパースチェックアウトの定義に密接に一致するようにインデックスのサイズを削減します。これにより、git statusgit add などのコマンドで大幅なパフォーマンス上の利点が得られます。この機能はまだ実験段階です。一部のコマンドは、この機能と適切に統合されるまで、スパースインデックスを使用すると遅くなる可能性があります。

警告: スパースインデックスを使用するには、外部ツールによって完全に理解されていない方法でインデックスを変更する必要があります。この互換性に問題がある場合は、git sparse-checkout init --no-sparse-index を実行して、インデックスをスパースではない状態に書き換えてください。古いバージョンの Git は、スパースディレクトリエントリのインデックス拡張機能を理解せず、無効にするまでリポジトリと対話できない場合があります。

add

スパースチェックアウトファイルに追加のディレクトリ(コーンモード)またはパターン(非コーンモード)を含めるように更新します。デフォルトでは、これらのディレクトリまたはパターンはコマンドライン引数から読み取られますが、--stdin オプションを使用して標準入力から読み取ることもできます。

reapply

作業ツリー内のパスに疎パターンルールを再適用します。マージやリベースなどのコマンドは、作業を行うためにパスを具体化することがあります(たとえば、競合を表示するため)。また、他の疎チェックアウトコマンドは、個々のファイルを疎化することに失敗する場合があります(たとえば、ステージングされていない変更や競合があるため)。このような場合、影響を受けるパスをクリーンアップした後(たとえば、競合の解決、変更の元に戻しまたはコミットなど)、後で git sparse-checkout reapply を実行することが理にかなっています。

reapply コマンドは、set コマンドのフラグと同じ意味で、--[no-]cone および --[no-]sparse-index フラグも受け入れることができます。これにより、すべての疎パスを再指定する必要なく、使用している疎モードを変更できます。

disable

core.sparseCheckout の設定を無効にし、作業ディレクトリをすべてのファイルを含む状態に戻します。

init

指定されたパスなしで set のように動作する非推奨のコマンドです。将来削除される可能性があります。

歴史的に、set は必要な設定をすべて処理しなかったため、initset の両方を呼び出す必要がありました。両方を呼び出すと、init ステップが最初にほとんどすべての追跡ファイル(コーンモードでは、無視されたファイルも)を削除し、次に set ステップが追跡ファイルの多く(無視されたファイルは含まない)を元に戻しました。失われたファイルに加えて、この組み合わせのパフォーマンスと UI は貧弱でした。

また、歴史的に、init はスパースチェックアウトファイルが既に存在する場合、実際にはそれを初期化しませんでした。これは、後続の set または add コマンドに渡すパスを覚えていなくても、スパースチェックアウトに戻ることが可能であることを意味しました。しかし、--cone および --sparse-index オプションは disable コマンドをまたいで記憶されなかったため、単に init を呼び出すだけの簡単な復元は利便性が低下しました。

check-rules

スパース性ルールが1つ以上のパスと一致するかどうかをチェックします。

デフォルトでは、check-rules は標準入力からパスのリストを読み込み、現在の疎化ルールに一致するパスのみを出力します。入力は1行に1つのパスで構成され、git ls-tree --name-only の出力と一致することが期待されます。これには、二重引用符 (") で始まるパス名が C スタイルの引用文字列として解釈されることも含まれます。

--rules-file <file> フラグを指定して呼び出すと、入力ファイルは現在のスパースチェックアウトルールではなく、<file> に見つかったスパースチェックアウトルールと照合されます。ファイル内のルールは、git sparse-checkout set --stdin で受け入れられるのと同じ形式であることが期待されます(特に、改行区切りである必要があります)。

デフォルトでは、--rules-file オプションに渡されるルールはコーンモードディレクトリとして解釈されます。--rules-file で非コーンモードパターンを渡すには、そのオプションと --no-cone オプションを組み合わせます。

-z フラグを指定して呼び出すと、標準入力へのパス入力と出力パスのフォーマットは \0 終端され、引用符で囲まれません。これは --rules-file オプションで渡されるルールのフォーマットには適用されないことに注意してください。

git sparse-checkout set MY/DIR1 SUB/DIR2

MY/DIR1/ と SUB/DIR2/ の下のすべてのファイル(任意の深さ)を作業コピーに含めるスパースチェックアウトに変更します(さらに MY/ と SUB/ の直下にあるすべてのファイルとトップレベルディレクトリも含む)。すでにスパースチェックアウト中の場合は、作業コピーに存在するファイルをこの新しい選択に変更します。このコマンドは、追跡ファイルも無視されていない追跡されていないファイルも存在しなくなったディレクトリ内の無視されたファイルをすべて削除することに注意してください。

git sparse-checkout disable

すべてのファイルで作業ディレクトリを再設定し、スパースチェックアウトを無効にします。

git sparse-checkout add SOME/DIR/ECTORY

SOME/DIR/ECTORY/ の下にあるすべてのファイル(任意の深さ)をスパースチェックアウトに追加し、SOME/DIR/ の直下と SOME/ の直下にあるすべてのファイルも追加します。このコマンドを使用する前に、すでにスパースチェックアウト中である必要があります。

git sparse-checkout reapply

コマンドが、選択された疎化ディレクトリを尊重しない方法で作業ツリーを更新する可能性があります。これは、Git 外部のツールがファイルを書き込むことによって発生する場合や、特別なケース(マージ/リベース時の競合など)や、一部のコマンドが疎化チェックアウトを完全にサポートしていなかった(例:古い recursive マージバックエンドは限られたサポートしか持っていなかった)ために Git コマンド自体に影響を与えることさえあります。このコマンドは、既存の疎化ディレクトリ指定を再適用して、作業ディレクトリを一致させます。

内部 — スパースチェックアウト

「スパースチェックアウト」は、作業ディレクトリを疎に格納することを可能にします。これは、skip-worktree ビット(git-update-index[1] を参照)を使用して、作業ディレクトリ内のファイルが考慮に値するかどうかを Git に伝えます。skip-worktree ビットが設定されており、ファイルが作業ツリーに存在しない場合、その不在は無視されます。Git はそれらのファイルのコンテンツを格納することを回避するため、スパースチェックアウトは、多くのファイルがあるリポジトリで作業しているが、現在のユーザーにとって重要なのはごく一部である場合に役立ちます。

$GIT_DIR/info/sparse-checkout ファイルは、skip-worktree 参照ビットマップを定義するために使用されます。Git が作業ディレクトリを更新すると、このファイルに基づいてインデックス内の skip-worktree ビットを更新します。ファイル内のパターンに一致するファイルは作業ディレクトリに表示され、残りのファイルは表示されません。

内部 — 非コーンモードの問題

set および add サブコマンドによって投入される $GIT_DIR/info/sparse-checkout ファイルは、.gitignore ファイルと同じ構文を使用して、多数のパターン(1行に1つ)として定義されます。コーンモードでは、これらのパターンはディレクトリに一致するように制限されます(ユーザーは常にディレクトリ名のみを提供または表示する必要があります)が、非コーンモードでは、gitignore スタイルのパターンが許可されます。非コーンモードで完全な gitignore スタイルのパターンを使用すると、いくつかの欠点があります。

  • 根本的に、様々な作業ツリー更新プロセス(プル、マージ、リベース、スイッチ、リセット、チェックアウトなど)が、N をパターン数、M をインデックス内のパス数とする O(N*M) のパターンマッチングを必要とします。これはスケールしません。

  • スケーリング問題を回避するには、先頭のディレクトリ名やグロブを指定することで、パターン数を制限する必要があります。

  • コマンドラインでグロブを渡すのはエラーが発生しやすく、ユーザーがグロブを引用符で囲むのを忘れると、シェルがそれをすべての一致するファイルに展開し、それらを個別に sparse-checkout set/add に渡してしまう可能性があります。これは「git grep -- *.c」などでも問題となる可能性がありますが、grep/log/status の間違いはすぐに結果に表示されます。sparse-checkout の場合、間違いは sparse-checkout コマンドが実行されたときに記録され、ユーザーが後でブランチを切り替えたり、リベースしたり、マージしたりするまで問題にならない可能性があり、ユーザーのエラーとそれに気づく機会との間に遅延が生じます。

  • 上記の項目に関連して、sparse-checkoutにはaddサブコマンドがありますが、removeサブコマンドはありません。仮にremoveサブコマンドが追加されたとしても、偶発的な引用符なしのグロブを取り消すことは「削除しすぎる」リスクを伴います。なぜなら、偶発的な追加の前に含まれていたエントリを削除してしまう可能性があるからです。

  • 非コーンモードでは、gitignoreスタイルのパターンを含めるもの(否定パターンを除く)を選択するために使用するのに対し、.gitignoreファイルでは、gitignoreスタイルのパターンを除外するもの(否定パターンを除く)を選択するために使用します。gitignoreスタイルのパターンに関するドキュメントは、通常、マッチングまたは非マッチングという用語ではなく、ユーザーが「除外」したいものについて説明しています。これにより、ユーザーが目的の動作を得るためにsparse-checkoutパターンを指定する方法を学ぼうとすると混乱が生じる可能性があります。

  • 「特別なパスパターンマッチング」を何らかの形で提供したい他のすべての git サブコマンドはパススペックを使用しますが、sparse-checkout の非コーンモードは gitignore パターンを使用しており、一貫性がないと感じられます。

  • 「正しい」動作が不明確なエッジケースがあります。2つの例

    First, two users are in a subdirectory, and the first runs
       git sparse-checkout set '/toplevel-dir/*.c'
    while the second runs
       git sparse-checkout set relative-dir
    Should those arguments be transliterated into
       current/subdirectory/toplevel-dir/*.c
    and
       current/subdirectory/relative-dir
    before inserting into the sparse-checkout file?  The user who typed
    the first command is probably aware that arguments to set/add are
    supposed to be patterns in non-cone mode, and probably would not be
    happy with such a transliteration.  However, many gitignore-style
    patterns are just paths, which might be what the user who typed the
    second command was thinking, and they'd be upset if their argument
    wasn't transliterated.
    Second, what should bash-completion complete on for set/add commands
    for non-cone users?  If it suggests paths, is it exacerbating the
    problem above?  Also, if it suggests paths, what if the user has a
    file or directory that begins with either a '!' or '#' or has a '*',
    '\', '?', '[', or ']' in its name?  And if it suggests paths, will
    it complete "/pro" to "/proc" (in the root filesystem) rather than to
    "/progress.txt" in the current directory?  (Note that users are
    likely to want to start paths with a leading '/' in non-cone mode,
    for the same reason that .gitignore files often have one.)
    Completing on files or directories might give nasty surprises in
    all these cases.
  • 過剰な柔軟性により、他の拡張機能は実質的に実用的ではなくなりました。--sparse-index は非コーンモードではおそらく不可能です。たとえ何らかの形で実現可能であったとしても、実装にははるかに多くの作業が必要であり、実際には遅すぎたかもしれません。部分クローンとスパースチェックアウト間の結合を追加するためのいくつかのアイデアも、より制限されたパスのセットでのみ実用的です。

これらすべての理由により、非コーンモードは非推奨です。コーンモードを使用するように切り替えてください。

内部 — コーンモード処理

デフォルトである「コーンモード」では、含めるディレクトリのみを指定できます。指定されたディレクトリについては、そのディレクトリ下のすべてのパスが含まれ、先行するディレクトリ(最上位ディレクトリを含む)の直下のパスもすべて含まれます。したがって、Documentation/technical/ ディレクトリを指定した場合、スパースチェックアウトには以下が含まれます。

  • トップレベルディレクトリ内のすべてのファイル

  • Documentation/ の直下にあるすべてのファイル

  • Documentation/technical/ の下にある任意の深さのすべてのファイル

また、コーンモードでは、ディレクトリが指定されていなくても、トップレベルディレクトリ内のファイルが含まれます。

コーンモードで疎チェックアウトパターンを変更すると、Git は疎チェックアウトコーン内にない追跡された各ディレクトリを検査し、追跡されていないファイルが含まれているかどうかを確認します。これらのファイルがすべて .gitignore パターンによって無視されている場合、そのディレクトリは削除されます。そのディレクトリ内の追跡されていないファイルのいずれかが無視されていない場合、そのディレクトリ内では削除は行われず、警告メッセージが表示されます。これらのファイルが重要である場合は、疎チェックアウトの定義をリセットしてそれらを含めるようにし、git add および git commit を使用してそれらを保存し、残りのファイルを手動で削除して、Git が最適に動作できるようにしてください。

ディレクトリが内部でスパースチェックアウトの完全なパターンセットのサブセットにどのように変換されるかについては、「内部 — コーンパターンセット」セクションも参照してください。

内部 — 完全なパターンセット

完全なパターンセットは、任意のパターンマッチングと複雑な包含/除外ルールを可能にします。これらは、インデックスを更新する際に O(N*M) のパターンマッチングを引き起こす可能性があり、ここで N はパターン数、M はインデックス内のパス数です。このパフォーマンスの問題に対処するため、core.sparseCheckoutCone が有効になっている場合、より制限されたパターンセットが許可されます。

スパースチェックアウトファイルは .gitignore ファイルと同じ構文を使用します。詳細については gitignore[5] を参照してください。ただし、ここでは通常、どのファイルを除外するかではなく、どのファイルを含めるかを選択するためにパターンが使用されます。(ただし、gitignoreスタイルのパターンには ! で始まるパターンによって否定が定義されているため、含めないファイルを選択することもできるため、少し混乱する可能性があります。)

例えば、すべてを選択し、その後ファイル unwanted を削除する(したがって、unwanted という名前のファイルを除くすべてのファイルが作業ツリーに表示される)には、次のようになります。

git sparse-checkout set --no-cone '/*' '!unwanted'

これらのパターンは $GIT_DIR/info/sparse-checkout にそのまま配置されるため、現時点でのそのファイルの内容は次のようになります。

/*
!unwanted

スパースチェックアウトで使用される gitignore スタイルのパターンについて詳しく学ぶには、git-read-tree[1] の「スパースチェックアウト」セクションも参照してください。

内部 — コーンパターンセット

コーンモードでは、ディレクトリのみが受け入れられますが、それらは完全なパターンセットで使用されるのと同じ gitignore スタイルのパターンに変換されます。そのモードで使用される特定のパターンを、次の2つのタイプのいずれかと呼びます。

  1. 再帰的: ディレクトリ内のすべてのパスが含まれます。

  2. 親: ディレクトリ内のすべてのファイルが直接含まれます。

コーンモードでは常にトップレベルのファイルが含まれるため、ディレクトリが指定されていない git sparse-checkout set を実行すると、トップレベルディレクトリが親パターンとして追加されます。この時点で、スパースチェックアウトファイルには次のパターンが含まれます。

/*
!/*/

これは、「トップレベルディレクトリの直下のすべてを含めるが、それより下のレベルのものは何もない」という意味です。

コーンモードでは、git sparse-checkout set サブコマンドはディレクトリのリストを受け取ります。コマンド git sparse-checkout set A/B/C は、ディレクトリ A/B/C を再帰パターンとして設定し、ディレクトリ A および A/B を親パターンとして追加します。結果として得られる sparse-checkout ファイルは次のようになります。

/*
!/*/
/A/
!/A/*/
/A/B/
!/A/B/*/
/A/B/C/

ここでは順序が重要であり、否定的なパターンはファイルの下位に現れる肯定的なパターンによって上書きされます。

core.sparseCheckoutCone が明示的に false に設定されていない限り、Git はこれらのタイプのパターンを想定してスパースチェックアウトファイルを解析します。パターンが一致しない場合、Git は警告します。パターンが期待される形式と一致する場合、Git はより高速なハッシュベースのアルゴリズムを使用してスパースチェックアウトへの包含を計算します。一致しない場合、Git は設定に関係なく、core.sparseCheckoutCone が false であるかのように動作します。

コーンモードの場合、完全なパターンが $GIT_DIR/info/sparse-checkout ファイルに書き込まれるという事実にもかかわらず、git sparse-checkout list サブコマンドは、再帰パターンを定義するディレクトリをリストします。上記の例のスパースチェックアウトファイルの場合、出力は次のようになります。

$ git sparse-checkout list
A/B/C

core.ignoreCase=true の場合、パターンマッチングアルゴリズムは大文字と小文字を区別しないチェックを使用します。これにより、git sparse-checkout set コマンドでの大文字小文字の不一致のファイル名が修正され、作業ディレクトリ内の期待されるコーンが反映されます。

内部 — サブモジュール

リポジトリに1つ以上のサブモジュールが含まれている場合、サブモジュールは git submodule コマンドとのやり取りに基づいて投入されます。具体的には、git submodule init -- <path><path> のサブモジュールが存在することを確認し、git submodule deinit [-f] -- <path><path> のサブモジュールのファイルを削除します(追跡されていないファイル、コミットされていない変更、プッシュされていない履歴を含む)。スパースチェックアウトが作業ツリーからファイルを削除してもインデックスにエントリを残すのと同様に、非初期化されたサブモジュールは作業ディレクトリから削除されますが、インデックスにはエントリが残ります。

サブモジュールにはプッシュされていない変更や追跡されていないファイルが含まれている可能性があるため、それらを削除するとデータが失われる可能性があります。したがって、スパースな包含/除外ルールを変更しても、すでにチェックアウトされているサブモジュールが作業コピーから削除されることはありません。言い換えれば、サブモジュールを削除または追加するブランチ間を切り替える場合でも、checkout がサブモジュールを自動的に削除または初期化しないのと同様に、sparse-checkout を使用して「興味深い」ファイルの範囲を縮小または拡大しても、サブモジュールが自動的に非初期化または初期化されることはありません。

さらに、上記の事実により、「追跡された」ファイルが作業コピーに存在しない可能性がある理由は複数あります。疎化パターン適用によるスパースチェックアウトと、サブモジュールの初期化状態です。したがって、作業コピー内の追跡されたファイルに対して動作する git grep などのコマンドは、これらの制限のいずれかまたは両方によって制限された結果を返す可能性があります。

GIT

git[1]スイートの一部

scroll-to-top