6月18日、nelson.cloudが「.gitignore Isn't the Only Way To Ignore Files in Git」と題した記事を公開した。.gitignore以外にも、Gitにはファイルを無視するための仕組みが2つ存在する。それぞれの用途を理解していないと、個人メモをうっかりコミットしたり、チームの.gitignoreをOS固有の設定で汚したりという事態を招く。
Gitを長年使っているエンジニアでも「無視したいファイルは.gitignoreに書く」で思考が止まっていることは多い。しかしGitには、ファイルを無視するための仕組みが3つのレベルで存在する。チームで共有すべき設定は.gitignore、自分だけの個人設定はリポジトリ単位なら.git/info/exclude、マシン全体なら~/.config/git/ignoreだ。この使い分けを知っているかどうかで、チーム開発時の細かなストレスが大きく変わる。
知らないと損する.git/info/exclude
最も見落とされがちなのが、**各リポジトリの.git/info/exclude**だ。
.gitディレクトリ内に存在するこのファイルは、.gitignoreと同じ書式でファイルを無視できる。決定的な違いは、Gitのコミット対象にならない点だ。つまり、このファイルへの変更は他のメンバーには一切影響しない。
典型的なユースケースは、作業中のリポジトリに置いた個人メモだ。notes.txtを手元に置いておきたいが、.gitignoreに追加してチームの設定を変えたくない――そういった場面に使える。個人の作業フローに依存するファイルを、チームの設定から切り離して管理できる。
マシン全体に効く~/.config/git/ignore
もう一つがグローバルな無視ファイル、~/.config/git/ignoreだ(XDG Base Directory仕様に基づくデフォルトパス)。ここに書いたファイル名は、そのマシン上の全リポジトリで一括して無視される。
代表的な例がmacOSの.DS_Storeだ。すべてのリポジトリで無視したいが、各リポジトリの.gitignoreに毎回書くのは非効率だし、チームのリポジトリに書くのも筋が悪い。OS固有のファイルやエディタが生成するファイル(JetBrains IDEの.idea/、Vimの*.swpなど)をグローバルで一元管理するのがこのファイルの用途だ。
なお、慣習的に~/.gitignore_globalが使われてきた経緯もあり、パスは任意に変更できる。~/.gitignore_globalを使いたければ以下のコマンドを実行する。
git config --global core.excludesFile ~/.gitignore_global
デフォルト(~/.config/git/ignore)に戻す場合はこちら。
git config --global --unset core.excludesFile
どのファイルが無視しているかを調べるgit check-ignore
3つの無視設定が絡み合うと、「なぜこのファイルが無視されているのか」が分かりにくくなる。そこで使えるのが**git check-ignore -v**コマンドだ。
.DS_Storeを例にすると、どの設定ファイルが無視を担っているかを以下のように特定できる。
.gitignoreが無視している場合:
$ git check-ignore -v .DS_Store
.gitignore:1:.DS_Store .DS_Store
.git/info/excludeが無視している場合:
$ git check-ignore -v .DS_Store
.git/info/exclude:7:.DS_Store .DS_Store
~/.config/git/ignoreが無視している場合:
$ git check-ignore -v .DS_Store
/Users/nelson/.config/git/ignore:2:.DS_Store .DS_Store
カスタムのグローバル無視ファイル(.gitignore_global)が無視している場合:
$ git check-ignore -v .DS_Store
/Users/nelson/.gitignore_global:1:.DS_Store .DS_Store
出力にはどのファイルの何行目で無視が設定されているかまで表示される。何も無視していなければ出力はない。トラブルシュートにも有効なコマンドだ。
詳細は.gitignore Isn't the Only Way To Ignore Files in Gitを参照していただきたい。