Git で .gitignore に書いたファイルが無視できない
.gitignore は新規ファイルにのみ作用するため、既に追跡済みのファイルは git rm --cached で一度インデックスから外せば無視できる。
書式やパス記法のミスにも注意する。
公開:
要約
.gitignore に書いたのに対象ファイルが Git の差分に出続ける場合、ほぼ必ず既に追跡済みであることが原因。.gitignore は新規(untracked)ファイルにしか作用しないので、git rm --cached でインデックスから一度外して commit すると以降は無視される。
よくある原因
- ファイルがすでに追跡されている: 一度 commit したファイルは、後から
.gitignoreに追記しても無視対象にならない。git ls-filesに出てくれば追跡済み。 - パターン記法の勘違い: 先頭の
/はリポジトリルート相対、末尾の/はディレクトリ限定、**は再帰的にマッチ、など仕様を誤って書いている。 - 複数の .gitignore の優先順位: サブディレクトリの
.gitignoreが親より優先される。
グローバル~/.config/git/ignoreの影響も受ける。 - 否定パターンの罠:
!patternは親ディレクトリ自体が無視されている場合は効かない。
解決策
1. 追跡済みファイルをインデックスから外す
最頻の原因。
ファイル自体は残したまま追跡だけ外す。
git rm --cached path/to/secrets.env
git commit -m "stop tracking secrets.env"ディレクトリごと外す場合は -r を付ける。
git rm -r --cached node_modulesその後 .gitignore に node_modules/ を追記して push する(公式ドキュメント)。
2. どの行が効いているか調べる
意図と違う場合は git check-ignore -v でルール元を特定できる。
$ git check-ignore -v build/index.js
.gitignore:5:build/ build/index.js無視対象でないなら何も出力されない。
3. パターン書式を整える
foo— 任意階層のfoo/foo— ルート直下のfooのみfoo/— ディレクトリのみ**/foo— 任意階層のfoo!foo— 一度無視されたものを復活
4. 再追跡したいケース
親ディレクトリで *.log を無視しつつ、特定ログだけ追跡したいときは否定を使う。
*.log
!important.logただし dist/ のようにディレクトリ自体を無視している場合、その内部ファイルを !dist/keep.txt で復活させることはできない。dist/* !dist/keep.txt のように一度内部を列挙する必要がある。
実行例
実際に alpine/git 環境(Git 2.52.0)で上記の手順を動かすと、追跡済みの secrets.env は .gitignore に記述済みであっても git status --short に M secrets.env として現れ続け、git check-ignore -v が終了コード 1(マッチ無し)を返すことで追跡状態のままであることが確認できる。
その後 git rm --cached でインデックスから外すと git status の出力から消え、git check-ignore -v が .gitignore:1:secrets.env とルールを正しく認識して終了コード 0 を返す。
== versions ==
git version 2.52.0
== run ==
--- 後から .gitignore に追記しても、すでに追跡済み ---
--- git status --short (無視されず M で出てしまう)---
M secrets.env
--- git check-ignore -v: 追跡済みファイルは何も表示されない(= 無視対象として扱われない)---
check-ignore の終了コード: 1(1 = マッチ無し)
--- 解決: git rm --cached でインデックスから外す ---
rm 'secrets.env'
--- 解決後: git status --short (secrets.env は出ない)---
(M secrets.env が消えていれば成功)
--- 解決後: git check-ignore -v(untracked になり今度はルールがマッチ)---
.gitignore:1:secrets.env secrets.env
check-ignore の終了コード: 0(0 = マッチ)
--- git ls-files (追跡対象から外れている)---
.gitignore— 2026-06-11 時点の出力