Gitでプロジェクトを管理する際、空ディレクトリはコミットしたいけど、ディレクトリ内のファイルはコミットしなくないケースがあったため、今回はその方法を備忘録としてまとめていきます。(非常に初歩的な内容です)
最終的な解決方法
最初に結論ですが、.gitkeep
と.gitignore
を組み合わせて以下の方法に着地しました。
!storage/
storage/*
!storage/.gitkeep
VSCode上でもディレクトリ内の.gitkeep
以外のファイルは追跡が無視されていることを確認できます。
記事にした背景
直面した課題
今回、個人開発したアプリケーションをデプロイし、動作させたところ下記のようなエラーが発生しました。
Error: ENOENT: no such file or directory, open './storage/sample.jpg'
よく遭遇する対象ディレクトリやファイルがない時に出るエラーです。ローカル環境では動作するのに、本番環境だとどうして動作しない。。。。色々調査していたところ、とんでもなく初歩的な失態に気付きました。
それが対象ディレクトリがリモートリポジトリにコミットできていない問題でした。
空ディレクトリも正常にコミットできるように配慮はしていましたが、正しくルールが書けていなかったために発生していたようです。
なぜ空ディレクトリがコミットできないのか
Gitはデフォルトで空ディレクトリをコミットできない仕様となっているとのこと。
どうやらファイルとディレクトリでは差分を追跡する際の扱い方が違うため、現状の仕様では対応できないらしい。
詳しい仕様については以下の記事を参考
実装の流れ
実装手順
空ディレクトリの作成
コミット対象となるディレクトリを作成します。
今回はstorage
ディレクトリという名前で作成しています。
$ mkdir storage
対象ディレクトリ内に.gitkeep
ファイルを作成
storageディレクトリ内に.gitkeep
ファイルを作成します。
ファイル内には特に何も書かなくても問題ない。
$ touch storage/.gitkeep
.gitignore
に対象ディレクトリに対するルールを記載
最初に書いていた通り、以下のようなルールを.gitignoreに記載する。
$ touch .gitignore
!storage/
storage/*
!storage/.gitkeep
- !storage
!
が先頭に付いている場合、そのディレクトリやファイルを gitignore の対象から除外。この場合、storage
ディレクトリ自体はGitの追跡対象となる。 - storage/*
storage
ディレクトリ内の全てのファイルとディレクトリを gitignore の対象に含める。これにより、storage
ディレクトリ内のファイルやディレクトリは、Gitの非追跡対象となり、コミットされない。 - !storage/.gitkeep
.gitkeep
ファイルを gitignore の対象から除外。これにより、storage/.gitkeep
ファイルはGitの追跡対象となる。この設定により、空のstorage
ディレクトリを Git リポジトリに含めることができる。
重要
③のルールが重要となりますが、私の場合はまさかの①を忘れていたという……
まとめ
このルールは、対象ディレクトリをコミット対象に含めつつ、その中のファイルは追跡対象から除外したい場合に有効な方法です。例えば、一時ファイルやキャッシュファイルなど、リポジトリに含めたくないけど、その受け皿は必要だからコミットしたいケースなどが想定できるかと思います。
非常に初歩的な内容でしたが、改めて細かい部分も整理できて良かったです。同じ過ちを繰り返さないように少しでも誰かの参考になれば幸いです。