Gitignore と Gitkeep:空ディレクトリの追跡
.gitignore と .gitkeep の違いを理解する。git で空ディレクトリを追跡する方法と、プロジェクトでそれぞれの規約をいつ使用すべきかを解説します。
詳細な説明
.gitignore と .gitkeep は正反対の問題を解決します:.gitignore は git にファイルを除外させ、.gitkeep は空のディレクトリを git に追跡させるための規約です。両方を理解することがリポジトリを正しく構成するために不可欠です。
問題:git は空ディレクトリを追跡しない
Git はファイルのみを追跡し、ディレクトリは追跡しません。空の logs/ ディレクトリを作成して git add logs/ を実行しても、何も起こりません。Git はそれを認識しません。これは設計によるもので、ディレクトリはその中のファイルがチェックアウトされたときに暗黙的に作成されます。
.gitkeep 規約:
.gitkeep は git の機能ではありません。ディレクトリを git に追跡させるために追加する空のプレースホルダーファイルというコミュニティ規約です:
logs/.gitkeep
uploads/.gitkeep
tmp/.gitkeep
ファイル名 .gitkeep は git にとって特別な意味を持ちません。.keep、.placeholder、README でも構いません。意図を明確に伝えるため、コミュニティは .gitkeep に落ち着きました。
.gitkeep を使用すべき場面:
- ランタイムディレクトリ — アプリケーションが起動時に
logs/やtmp/ディレクトリの存在を期待する場合。これがないと初回実行時にクラッシュします。.gitkeepによりクローン時にディレクトリが作成されることが保証されます。 - アップロードディレクトリ — Web フレームワークがファイルアップロードを処理するために
uploads/フォルダの存在を期待する場合。 - プロジェクトスキャフォールディング — 計画された構造を表す空のモジュールディレクトリで、後で埋められるもの。
.gitignore と .gitkeep の組み合わせ:
一般的で強力なパターンは、ディレクトリの内容を無視しつつディレクトリ自体を保持することです:
# .gitignore
logs/*
!logs/.gitkeep
これによりすべてのログファイルは無視されますが、.gitkeep は保持され、クリーンクローン後も logs/ ディレクトリが存在します。
代替案:ディレクトリ内の .gitignore:
.gitkeep の代わりに、空ディレクトリ内に .gitignore ファイルを配置できます:
# logs/.gitignore
*
!.gitignore
これによりディレクトリ内のすべてのファイル(将来のログを含む)が無視され、.gitignore ファイル自体が git にディレクトリを追跡させます。このアプローチは、無視ルールが適用される場所に正確に存在するため自己文書化されています。
ベストプラクティス: 内容を常に無視すべきディレクトリ(ログ、キャッシュ、アップロード)にはディレクトリ内の .gitignore アプローチを使用し、プロジェクトスキャフォールドの一部である本当に空のディレクトリには .gitkeep を使用してください。
ユースケース
フレームワークのスキャフォールディングツールがログ、アップロード、キャッシュ用の空ディレクトリを生成しますが、開発者がリポジトリをクローンした際にそれらが存在する必要がある一方で、ランタイムの内容は追跡されるべきではありません。