.gitignore 構文とパターンマッチング規則
ワイルドカード glob、先頭・末尾スラッシュの挙動の違い、! 否定ルールにおける「ディレクトリ除外の罠」など Git 除外パターンの仕様を網羅。
.gitignore ファイルの各行は独立した除外パターンを表します。基本書式には 3 つの原則があります:
- 空行は完全に無視され、可読性を高めるための区切りとして利用できます。
- # で始まる行はコメントとして扱われ、Git のファイル追跡に一切影響を与えません。
- 行末のスペースは無視されます。末尾スペースをパターンに含める場合はバックスラッシュ (\ ) でエスケープします。
# Ignore compiled Python bytecode
__pycache__/
*.py[cod]
# Ignore local secret configurations
.env
.env.localGit は単一ディレクトリ階層内において、Unix シェル標準の glob ワイルドカードをサポートしています:
- * (アスタリスク): 単一パス階層内の 0 文字以上の文字列にマッチします。*.log は error.log にマッチしますが、階層固定時は nested/error.log にはマッチしません。
- ? (疑問符): 任意の 1 文字だけにマッチします。test?.js は test1.js や testA.js にマッチしますが、test12.js にはマッチしません。
- [abc] (文字範囲): ブラケット内の任意の 1 文字にマッチします。*.[oa] は .o または .a で終わるファイルにマッチします。
スラッシュ (/) の配置位置によって、Git のパターン解釈は根本的に変化します:
- 末尾スラッシュ (logs/): ディレクトリのみに限定してマッチします。logs/ ディレクトリは除外されますが、同名の通常ファイル logs は除外されません。
- 先頭スラッシュ (/config.json): .gitignore が存在するルートディレクトリにパスを固定(アンカー)します。/config.json のみ除外し、サブフォルダの /packages/app/config.json は追跡対象のまま残せます。
- 中間スラッシュ (docs/*.html): パスの途中にスラッシュが存在する場合も、.gitignore があるディレクトリからの相対パスとして評価されます。
二重アスタリスク (**) を使用すると、複数のディレクトリ階層を横断して再帰的にマッチングできます:
- **/cache: リポジトリ内のどの階層にある cache フォルダやファイルにもマッチします (cache, src/cache, a/b/c/cache など)。
- logs/**: logs/ ディレクトリ配下にあるすべてのファイルおよびサブディレクトリに再帰的にマッチします。
- a/**/b: a/b, a/x/b, a/x/y/b など、中間に挟まる任意階層にマッチします。
感嘆符 (!) をパターンの先頭に付けると、それ以前のルールで除外されたファイルを再度追跡対象に含める(ホワイトリスト化する)ことができます。
Git は高速化のため、ディレクトリ自体が除外設定されている場合、その配下の走査を完全にスキップします。親ディレクトリを build/ で除外している場合、いくら後から !build/important.txt と書いても Git はそのファイルを再読み込みしません。
除外されたフォルダ内の特定ファイルを例外として追跡するには、フォルダ自体ではなく「フォルダの中身」を除外した上で、目的のファイルをホワイトリスト指定する必要があります:
# INCORRECT: Will NOT work because parent directory is skipped
node_modules/
!node_modules/my-local-package
# CORRECT: Ignore contents of directory, then whitelist the specific target
node_modules/*
!node_modules/my-local-package/ファイルが意図せず除外されている場合や、逆に除外されない原因を調査するには、Git 組み込みの診断コマンドを -v (詳細) オプション付きで実行します:
# Shows the exact .gitignore file and line number responsible
git check-ignore -v src/temp/debug.logよくある質問 (FAQ)
.gitignore の書き方、キャッシュ削除、リポジトリ管理に関するエンジニアの疑問に回答します。
.gitignore における * と ** の違いは何ですか?
単一アスタリスク (*) は単一のフォルダ階層内での文字列にマッチします。二重アスタリスク (**) は任意の深さのサブディレクトリ階層を横断してマッチします。
フォルダを除外した後に !folder/file.txt を書いても反映されないのはなぜですか?
Git は親フォルダが除外されていると、内部の走査をスキップするためです。'folder/*' のようにフォルダ配下の要素を除外した上で '!folder/file.txt' を指定する必要があります。
どのルールによってファイルが無視されているか調べるには?
'git check-ignore -v <ファイルパス>' を実行してください。対象ファイルを除外している .gitignore のファイル名と該当行番号が表示されます。