! を使った Gitignore 否定パターンの解説
! プレフィックスを使った gitignore 否定パターンをマスター。ディレクトリを無視しつつ特定ファイルを保持する方法、ネストされた例外、よくある落とし穴を解説します。
詳細な説明
gitignore の否定(! プレフィックス)は、より広いパターンで除外されたファイルを再包含する機能です。.gitignore の最も強力で、最も混乱しやすい機能の1つです。
基本構文:
# Ignore everything in build/
build/*
# But keep the .gitkeep file
!build/.gitkeep
! プレフィックスは、特定のファイルまたはパターンに対して以前の無視ルールを反転させます。
重要な落とし穴 — 親ディレクトリ:
否定は、親ディレクトリが無視されている場合、ファイルを再包含できません。これが混乱の最大の原因です:
# THIS DOES NOT WORK:
build/
!build/important.txt
git が build/(末尾スラッシュ付き)を無視する場合、そのディレクトリの中を一切見ません。important.txt の否定は評価されません。修正方法はワイルドカードを使用することです:
# THIS WORKS:
build/*
!build/important.txt
build/* を使用すると build/ の内容は無視されますが、git がディレクトリを走査して否定されたファイルを発見できるようになります。
ネストされたディレクトリの否定:
無視されたディレクトリの深い場所にあるファイルを保持するには、すべてのレベルで否定が必要です:
# Ignore all of vendor except a specific package
vendor/*
!vendor/critical-package/
vendor/critical-package/*
!vendor/critical-package/src/
git が中に入って走査できるように、各ディレクトリレベルを明示的に許可する必要があります。
一般的なユースケース:
- 空ディレクトリの保持 — Git は空ディレクトリを追跡しません。
.gitkeep規約を使用します:
logs/*
!logs/.gitkeep
- 特定の IDE 設定の共有:
.vscode/*
!.vscode/settings.json
!.vscode/extensions.json
- 特定のファイルタイプ以外をすべて無視:
*
!*.py
!*/
注意:git がサブディレクトリに入ってマッチするファイルを見つけられるように、!*/ も否定する必要があります。
順序が重要: ルールは上から下に処理されます。後のルールが前のルールをオーバーライドします。否定は、オーバーライドしたい広い無視ルールの後に配置する必要があります。
デバッグ: git check-ignore -v <path> を使用して、特定のパスに影響しているルール(どのファイルのどの行か)を正確に確認できます。
ユースケース
開発者が、アップストリームの修正がリリースされるまで追跡する必要があるローカルパッチ済みパッケージを除き、vendor ディレクトリ全体を無視する必要があります。