できない.dev

Git で .gitignore に書いたファイルが無視できない

.gitignore は新規ファイルにのみ作用するため、既に追跡済みのファイルは git rm --cached で一度インデックスから外せば無視できる。
書式やパス記法のミスにも注意する。

#gitignore#untracked#index#exclude

公開:

要約

.gitignore に書いたのに対象ファイルが Git の差分に出続ける場合、ほぼ必ず既に追跡済みであることが原因。.gitignore は新規(untracked)ファイルにしか作用しないので、git rm --cached でインデックスから一度外して commit すると以降は無視される。

よくある原因

  1. ファイルがすでに追跡されている: 一度 commit したファイルは、後から .gitignore に追記しても無視対象にならない。git ls-files に出てくれば追跡済み。
  2. パターン記法の勘違い: 先頭の / はリポジトリルート相対、末尾の / はディレクトリ限定、** は再帰的にマッチ、など仕様を誤って書いている。
  3. 複数の .gitignore の優先順位: サブディレクトリの .gitignore が親より優先される。
    グローバル ~/.config/git/ignore の影響も受ける。
  4. 否定パターンの罠: !pattern は親ディレクトリ自体が無視されている場合は効かない。

解決策

1. 追跡済みファイルをインデックスから外す

最頻の原因。
ファイル自体は残したまま追跡だけ外す。

git rm --cached path/to/secrets.env
git commit -m "stop tracking secrets.env"

ディレクトリごと外す場合は -r を付ける。

git rm -r --cached node_modules

その後 .gitignorenode_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 時点の出力

この記事は役立ちましたか?