- Git のファイル無視ルールは共有範囲に応じて
.gitignore、.git/info/exclude、~/.config/git/ignore の 3つのレベルに分かれる
.gitignore はリポジトリのコードと一緒にコミットされるため、チームやプロジェクトで一緒に適用すべき 共有ルール を置く場所である
- 個人用ファイルやローカル作業用ファイルのように、リポジトリには存在していてもチームのルールにするには微妙な項目は
.git/info/exclude に置くのが適している
- macOS の
.DS_Store のように、すべてのリポジトリで繰り返し除外したいファイルは マシン全体の ignore ファイル である ~/.config/git/ignore に入れられる
git check-ignore -v <ファイル名> は、どのルールがファイルを無視しているのかを追跡するときに便利で、マッチするルールがなければ何も出力されない
Git ignore ルールの適用場所
- Git はファイル無視ルールを3つの場所で処理できる
.gitignore
.git/info/exclude
~/.config/git/ignore
.gitignore: リポジトリにコミットされる共有ルール
.gitignore は無視するファイル名を書く一般的なファイルである
- ほかのコードと一緒に Git にチェックイン される
.gitignore のルールにマッチするファイルは git コマンド実行時に考慮されない
.git/info/exclude: リポジトリごとの個人ルール
exclude ファイルはすべての Git リポジトリの .git ディレクトリ内にある
- このファイルの変更は Git にチェックインされない
- 新しい Git リポジトリでは通常、数行のコメントが入っている
- リポジトリごとにだけ無視したいが
.gitignore には入れたくないファイルに適している
- 例: 個人のワークフローでのみ必要な
notes.txt をリポジトリにコミットせず、プロジェクトの .gitignore にも追加したくないなら、.git/info/exclude に notes.txt を追加する
~/.config/git/ignore: マシン全体のルール
- グローバル
ignore ファイルはホームディレクトリの ~/.config/git/ignore にある
- ここに追加したファイル名は マシンレベルでグローバルに無視 される
- Git にチェックインされず、特定のリポジトリにも結び付いていない
- コンピュータ上のすべての Git リポジトリで無視したいファイルを入れるのに向いている
- 例: macOS では
.DS_Store をここに追加するのが適している
グローバル ignore ファイルのパスを変更する
- グローバル ignore ファイルは別のファイルに指定できる
- グローバル Git ignore ファイルを
.gitignore_global にしたい場合は、次のコマンドを実行する
git config --global core.excludesFile ~/.gitignore_global
git config --global --unset core.excludesFile
どのルールがファイルを無視しているか確認する
git check-ignore -v <ファイル名> で、特定のファイルがどのルールによって無視されているか確認できる
.DS_Store がどのように無視されるか確認するには、Git リポジトリ内で次のコマンドを実行する
git check-ignore -v .DS_Store
- リポジトリの
.gitignore が .DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
.gitignore:1:.DS_Store .DS_Store
- リポジトリの
.git/info/exclude が .DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
.git/info/exclude:7:.DS_Store .DS_Store
- グローバル
~/.config/git/ignore ファイルが .DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
/Users/nelson/.config/git/ignore:2:.DS_Store .DS_Store
- ユーザー指定のグローバル ignore ファイル
.gitignore_global が .DS_Store を無視している場合の出力例は次のとおり
$ git check-ignore -v .DS_Store
/Users/nelson/.gitignore_global:1:.DS_Store .DS_Store
- 特定のファイルを無視するルールがなければ、
git check-ignore -v コマンドは 何も出力しない
3件のコメント
作業のSpecや
plan.mdのようなファイルを.git/info/excludeに入れておくのも便利そうですねルートに設定するものがあったんですね(笑)
Hacker Newsのコメント
面白い記事だが、Gitで一番気に入っているほぼ無視する機能である
.gitattributesが抜けているこのファイルでは、特定のファイルの差分をGitに"無視"させるよう指定できる。たとえばNodeプロジェクトの
package-lock.jsonは、Gitの観点ではほとんど純粋なノイズに近い。ライブラリの具体的なバージョンが入った巨大な差分ばかりが出て、人間が読みやすい実際のバージョン情報は別のpackage.jsonにあるプロジェクトルートの
.gitattributesにpackage-lock.json -diffと1行追加すれば、ファイルは引き続きステージング/コミットされるが、git diffでは意味のない巨大な差分が見えなくなるpackage-lock.jsonがノイズであってはならない。意図的に更新しようとしているのでなければ更新すべきではないし、そうでなければ理由もなくサプライチェーンリスクにさらされるpackage-lock.jsonの変更がしばしば予期せず発生するなら、何かを間違っているpackage-lock.jsonはすべての推移的依存関係を示し、package.jsonは直接依存関係しか示さない。後者が「人間が読める本当のバージョン」だというのは事実ではない両者は目的が異なり、ロックファイルの差分を常に無視してよいと言うのは危険だ
git diffがロックファイルの差分を見せてくれないのは本当に腹が立ちそうだ行単位のノイズに見えるというのは理解できるが、必要なときには絶対に必要だ
グローバル/ユーザー単位の除外設定は、もっと広く知られてよい機能だ。IDE/OS/AI関連ファイルをすべてのプロジェクトの
.gitignoreに追加しようとする変更をよく受けるが、標準設定に入れればどこでも無視され、各プロジェクトを触る必要もなく、.gitignoreを更新していないプロジェクトで誤ってコミットするリスクもないと伝えると、たいてい歓迎される個人的な原則として、リポジトリ内の
.gitignoreはビルド成果物や依存関係フォルダのようなリポジトリ専用の項目にだけ使い、たいていのユーザーツールは各自のユーザー設定に置くべきだと思っている.gitignore設定をたびたび案内しなければならないのは、リポジトリ内の.gitignoreをリポジトリ専用の項目にだけ使うという原則の当然の帰結だみんなの時間を節約するには、そうしたファイルは単にすべてのプロジェクトの
.gitignoreに入れてしまうほうがよい.gitignoreに入れてきたどうせ後でGitから削除することになるし、その人にとってもつらいので、親切心で先回りして防いでいた。今後はそこまで親切にしないかもしれない
gitignoreのほうを好むgitignoreを避けるなら、生成スクリプトやボリュームで設定を復元/維持できるが、.gitignore1行の代わりに追加スクリプトやdevcontainerのマウント設定が必要になるグローバルGit設定と無視ファイルは、
~/.gitignore_globalを作って設定を変えるより、~/.config/git/ignoreと~/.config/git/configに置くのが正しいと思う~/.config/をさまざまな用途に活用すれば、ルートレベルのdotfilesはずっと少なくなるGit excludeがあまり使われない理由は、リポジトリにコミットされないので、使いたくなるたびに作り直さなければならないからだ。悪いという意味ではなく、あまり使われない理由がそれだということ
~/.configディレクトリをバージョン管理すれば、後で変更したり共有したりできる~/.cvsignoreを使ってもよいどこで学んだのか覚えていないが、グローバルGit ignoreに
atticを追加してあるそうすると、どのプロジェクトでも絶対にコミットしてはいけない雑多なものを置くための
atticディレクトリを作れる。実際にそういうディレクトリをチェックするリポジトリはまだ見たことがないatticのようなディレクトリがあるなら、その中にattic/.gitignoreを作って/**を入れれば、そのディレクトリと中のすべてが無視され、ignoreファイル自体も無視される普段は自分の版のディレクトリ名をU+1F4A9の1文字にしているが、HNはコメントにそれを入れるのを許していない
auxを使っているその中にアスタリスク1つ
*だけ入った.gitignoreを置いて隠せば、自分自身と中身すべてを無視する.localにしているscratch/だまだ足をすくわれたことはない
ユーザー別の無視について、macOSなら
.DS_Storeをそこに追加するのが理想的だと言われるが、プロジェクトのすべてのMac利用者がそうしなければならない2人以上いるなら、各自に任せないほうがよいかもしれない
~/.gitignore_globalファイルに.DS_Storeの項目があり、グローバルGit設定にもそのファイルの項目を無視する設定が入っている新しいMacのこのファイルの日付は注文の2日前で、自分で設定した記憶がないので、最初から入っていた気がする。古いMacも似たようなものだったと思うし、macOSのバージョンを見ると、かなり前からこれがデフォルトだった可能性もある
だから、
.DS_Store/を.gitignoreに追加しなければならなかった時代はもう終わったのかもしれないうわ、どうしてこれを知らなかったんだ? 20年選手のプロのソフトウェア開発者なのに、
.gitignoreしか使ってこなかった自分にしか関係のないあらゆる除外項目で
.gitignoreを散らかすよりよい方法があるのではと、自分に問いかけたことすらなかったと気づいた。ただ目の前の世界をそのまま受け入れていたんだ今日、世界が少しだけよくなった
.git/info/excludeを本当によく使う。ローカルでしか使わず、共同作業者には不要だったり使えなかったりするスクリプト/Makefileにとても向いているgit statusに出てくる未追跡ファイルを全部.git/info/excludeに押し込むシェル関数を使っているたいていは、リポジトリに入れたいものを
addとcommitしたあとで適用する複数のリポジトリが入っているプロジェクトディレクトリに対して、プロジェクト単位のGit設定を別々に適用するために、excludesファイルをこう使っている
https://laszlo.nu/blog/project-level-git-config.html
関連して使っているエイリアスがある
assume = update-index --assume-unchangedunassume = update-index --no-assume-unchangedassumed = "!git ls-files -v | grep ^h | cut -c 3-"unassumeall = "!git assumed | xargs git update-index --no-assume-unchanged"assumeall = "!git st -s | awk {'print $2'} | xargs git assume"すでに追跡中のファイルには
git update-index --[no]-skip-worktreeもあるローカルでの実験に便利なことがあるが、Gitがあまり目立つ場所に出してくれない機能なので少し使いにくい。設定したことを覚えておく必要があり、忘れるとチェックアウトのような別の作業が妨げられることがある