空のディレクトリをコミットに含めたいときは、2つのやり方があります。.gitkeep
を使う方法 と、 .gitignore
をおいておく方法(例えばPHPのフレームワーク Laravel
で用いられている方法)です。
空のディレクトリを保持する目的で使用する .gitignore
は、たいていの場合、以下のような内容になっています。
*
!.gitignore
使い分けの基準
.gitkeep
と .gitignore
は、「空のディレクトリにファイルが追加されたときに、そのファイルを Git での管理対象に含めたいか?」という基準で、使い分けられます。
含めたい場合は .gitkeep
、含めたくない場合は .gitignore
を使います。
.gitkeep
を使う基準と例
.gitkeep
は、「デフォルトではファイルが存在しないけれど、ファイルが追加されたら、そのファイルを Git での管理対象にしたい」場合 に使います。
例えば、lumen の databse/migration
ディレクトリなどは、良い例です。
このディレクトリは、データベースの初期化をするスクリプトをおいておくために使われるディレクトリなので、「フレームワーク開発者的には、 デフォルトでおいておくファイルは特にない。しかし、 ユーザが 作ったファイルは Git でバージョン管理する対象にしたい 」というユースケースが容易に想定できるので、 .gitkeep
が使われています。
.gitignore
を使う基準と例
.gitignore
は、「デフォルトではファイルが存在しないし、そこに作られたファイルもバージョン管理したくない」場合 に使います。
例えば、「ログの出力先」やキャッシュ置き場などです。ログファイルやキャッシュファイルは、 バージョン管理する必要がありません。むしろ、したくないでしょう。
そもそも空のディレクトリをコミットに含めるべきではない例
コンパイル言語では、コンパイルで出力されるファイルを、「プロジェクトルートの .gitignore
に拡張子を指定して書かれている」ことが多いと思います。例えばC++やJava がそうです。その結果、コンパイル結果の出力先ディレクトリは空になるので、 Git の管理対象から外れます。
これは、その言語のユーザに 「コンパイル結果の出力先ディレクトリの名前」が一般的に共通認識として知れ渡っており、ディレクトリ構成として明示的に維持しておく必要性がない ため、このアプローチで良いと思います。
空のディレクトリのバージョン管理方法の良くない例
コミットに含めるべきなのに含められていない例
コンパイル結果の出力先ディレクトリは、ディレクトリ自体をバージョン管理の対象に含めなくて良い、と言いました。しかし、 TypeScript は別です。
TypeScript の、コンパイル結果の出力先のディレクトリは、バージョン管理の対象になっていないことが多いようです。例えば、ionic の dist
ディレクトリなどがそうです。
拡張子 .js
は、ヘルパースクリプトを書いたりしたときや、 gulp.js
などに使用されるので、他のコンパイル言語と違って、 拡張子を用いて .gitignore
できません 。
さらに、出力されるディレクトリを指定するにしても、一般的な共通認識がないため、ディレクトリを .gitignore
に追加すべきではありません。なぜなら、ディレクトリ自体をバージョン管理の対象から外してしまった場合、プロジェクトのディレクトリ構造がわからなくなってしまいます。
わざわざディレクトリ構造を調べるためだけに、 package.json
や gulp.js
に処理を追加するのは馬鹿げている、と私は思います。
ここまで読んできた方なら、この場合では「 空のディレクトリを保持する目的で使用する .gitignore
」を用いるのが適切だとわかるでしょう。
独自路線を行こうとしてミスっていた、CakePHP
これは、あとからプロジェクトルートの .gitignore
を調整したパターンです。
CakePHP では、そのディレクトリがデフォルトで空であることを、empty という名前のファイルを置いて、示していました。これは、(おそらく)empty ファイルをコミットした後で、プロジェクトルートの .gitignore
に「ディレクトリ構成は維持したいけれど、ファイルはバージョン管理したくない」ディレクトリを追加したのかなと思います。
「今現在の .gitignore のルールでは、バージョン管理の対象にならないディレクトリが、なぜ含まれているのだろう?」と疑問に思う人も少なくないでしょう。
冪等性が保てていない様に見えるので、私はこの方法はやめたほうがいいんじゃないかなと思います。