「.gitignore に書いたのに、なぜか無視されない…。」
ログやビルド成果物のようなディレクトリで一度はぶつかる定番の悩みです。原因のほとんどはシンプルで、そのファイル(やフォルダ)がすでに Git の“追跡対象”になっていること。.gitignore は「これから追跡しない」ための仕組みなので、いったん追跡から外す手順が必要です。
ここで迷いやすいのが git rm と git rm --cached の違い。
git rmは 追跡から外す+物理削除(ローカルからも消える)git rm --cachedは 追跡から外すだけ(ローカルには残る)
ログやキャッシュのようにローカルには残したいものは --cached を使うのが基本です。
この記事では、.gitignore が効かないときの安全で再現性の高い直し方を、チェックリストと実例でコンパクトにまとめます。先に正しい ignore パターンを記述し、git rm -r --cached → コミット → 検証までを一気通貫で解説。git check-ignore -v を使った確認方法や、.gitkeep だけ例外的に残す書き方、チーム運用での注意点も取り上げます。
この記事でわかること
.gitignoreが効かない根本原因と考え方git rm/git rm --cachedの使い分け(失敗しない判断基準)- 直し方の最短手順(パターン記述 → 追跡解除 → 確認 → コミット)
- ありがちミス(パスの基準、
/と/**、否定パターン!など)の回避策
※機密ファイルをコミットしてしまった場合は、
--cachedだけでなく履歴からの除去(filter-repo / BFG 等)が必要です。本記事ではまず日常運用での“効かない問題”解消にフォーカスします。
結論(TL;DR)
- 先に
.gitignoreに正しいパターンを書く - 追跡解除(物理は残す):
git rm -r --cached <対象パス>git add .gitignoregit commit -m "chore: stop tracking and ignore <対象パス>" git statusとgit check-ignore -vで効いていることを確認
ポイント:
.gitignoreの修正より先にgit rm --cachedを実行すると、後のgit addでまた拾ってしまうことがあるため、必ず「ルール記述→追跡解除」の順に。
.gitignore が効かない根本原因
.gitignoreは 未追跡(untracked) のファイルにのみ効果があります。- 既にコミット済み or 追加済み(tracked) のものには影響しません。
- つまり、index(追跡リスト)から外す=
git rm --cachedが必要。
git rm と git rm --cached の違い(ここが超重要)
結論だけ先に
git rm <path>… 追跡から外す+物理ファイルも削除(作業ツリーから消える)git rm --cached <path>… 追跡から外すだけ(物理ファイルは残る)
どちらを使う?
- ログ/ビルド/キャッシュなど「ローカルには残したい」もの →
--cachedが基本 - 本当に消したいファイル(誤コミットした鍵など) →
git rm(物理削除)- ※機密情報は履歴からの完全除去(
git filter-repo/ BFG Repo-Cleaner)も検討
- ※機密情報は履歴からの完全除去(
| 観点 | git rm | git rm --cached |
|---|---|---|
| 追跡状態 | 外す | 外す |
| 物理ファイル | 削除する | 残す |
| 典型用途 | 本当に消したいもの | ログ・ビルド・キャッシュ |
| チーム影響 | pullで消える | pullで追跡が外れるだけ |
最短レシピ:.gitignore → 追跡解除 → 確認 → コミット
1) .gitignore に正しいルールを書く
例:tmp/cache/logs/v3.0/ 以下をすべて無視する
# v3.0 配下は全部無視
tmp/cache/logs/v3.0/**
ルールの基礎
先頭
/… リポジトリルートからの絶対指定
末尾/… ディレクトリ限定**… 任意の階層にマッチ
否定!… 例外(後述)
2) 追跡解除(物理ファイルは残す)
git rm -r --cached tmp/cache/logs/v3.0
- 変更が多くて止められる場合は
-fを付けることもあります(要注意)。
3) 確認
git status
git check-ignore -v tmp/cache/logs/v3.0/some.log # どのルールで無視されたかが出る
4) コミット
git add .gitignore
git commit -m "chore: stop tracking tmp/cache/logs/v3.0 and ignore it"
実例:tmp/cache/logs/v3.0/ を“全部無視”、.gitkeep だけ追跡
.gitkeep を残すことで空ディレクトリ構造を共有したい、という実務はよくあります。
# v3.0 配下は全部無視
tmp/cache/logs/v3.0/**
# ただし .gitkeep は追跡する
!tmp/cache/logs/v3.0/.gitkeep
コマンド:
git rm -r --cached tmp/cache/logs/v3.0
git add .gitignore tmp/cache/logs/v3.0/.gitkeep
git commit -m "chore: ignore logs v3.0 but keep .gitkeep"
まだ効かない?「つまずきあるある」チェックリスト
- 順序問題(最後の一致が有効)
- 例外
!の行は、対象を無視する行の後に書く必要があります。 - 悪例:先に
!file、後でdir/**と書くとfileも無視される。
- 例外
- パス基準の勘違い
- 先頭
/はリポジトリルート基準。 - 先頭
/が無いと、どの階層でもマッチする可能性があります。 .gitignoreをサブディレクトリに置く場合、その場所基準の相対にもなる点に注意。
- 先頭
- ディレクトリ指定の
/抜けlogsとlogs/は意味が違います。ディレクトリだけを対象にするなら末尾/を付ける。
- Windows のパス区切り
.gitignoreの区切りは/固定。バックスラッシュ\は使いません。
- 既に追跡されている
- そもそも
git rm --cachedを実施していない/コミットしていない。 git ls-files <path>で追跡中かを確認。
- そもそも
- 除外は効いているが強制追加している
git add -f <file>を使うと無視ルールを強制突破します。不要なら外しましょう。
- 別の場所での除外設定
.git/info/excludeやグローバル.gitignore_globalに競合するルールが無いか。
任意階層にある logs ディレクトリをすべて無視
logs/
リポジトリ直下の logs/ だけ無視
/logs/
拡張子が .log のファイルを無視
*.log
深い階層も含めて logs 配下をすべて無視
logs/**
すべて無視しつつ .gitkeep は追跡する
logs/**
!logs/.gitkeep
よくあるQ&A
Q1. .gitignore を直したのに効きません。
A. 変更前に既に追跡されている可能性が高いです。git rm -r --cached <対象> → コミットまで行いましょう。
Q2. git rm と git rm --cached はどちらを使う?
A. ログ/ビルド/キャッシュなどローカルに残したいものは --cached。完全に消すなら git rm。機密は履歴除去も。
Q3. 空ディレクトリを共有したい
A. .gitkeep を置いて、否定パターン ! で例外にします。
Q4. ルールが当たっているか確認したい
A. git check-ignore -v <path> を使うと、どの行でマッチしたかが見えて便利。
チーム運用のベストプラクティス
- PRテンプレにチェック項目
.gitignore変更時はgit rm --cachedのコミットを含めたか.gitkeepなど例外が必要な場合、否定ルールの順序は正しいか
- 生成物は常に無視
vendor/、node_modules/、storage/logs/、ビルド成果物などは最初から除外
- ルールは“疎”に保つ
- 複雑なワイルドカードは検証を前提に(
git check-ignore -v)
- 複雑なワイルドカードは検証を前提に(
- 機密は即時対応
- 誤ってコミットした秘密鍵・認証情報は、履歴ごと削除+速やかに鍵をローテーション
まとめ
.gitignore が効かない原因の本質は、対象がすでに Git に「追跡済み」であることです。解決の基本線はシンプルで、まず .gitignore に正しいルールを記述し、そのうえで git rm -r --cached <対象> で追跡だけを外し、コミットして状態を確定させます。最後に git check-ignore -v <path> でどのルールに一致したかを確認すれば、再発しにくい“根拠ある直し方”になります。
また、git rm は「追跡解除+物理削除」、git rm --cached は「追跡解除のみ」という違いを理解しておくと運用が安定します。ログやビルド成果物のようにローカルには残したいものは --cached を原則に、逆に完全に消したいものは git rm を選びます。万一、機密情報をコミットしてしまった場合は、単なる追跡解除では不十分で、履歴からの除去(filter-repo/BFG 等)と秘密情報の速やかなローテーションが必要です。
日々の開発では、この手順をチームの標準にしておくと、同種のトラブルはぐっと減ります。ルールを先に書く → 追跡を外す → 動作を検証する――この流れを一度身体で覚えてしまえば、.gitignore まわりで迷う時間はほぼゼロになります。
参照リンク
- teratailの該当Q&A:「git ignoreがうまく働かない」
https://teratail.com/questions/mqdd4gphoed27f 。(teratail[テラテイル]) - Git公式ドキュメント:
.gitignore(パターンの優先順位/“既に追跡済みは対象外”の注記あり)
https://git-scm.com/docs/gitignore 。(Git) - Git公式ドキュメント:
git rm(--cachedで「インデックスのみから削除」)
https://git-scm.com/docs/git-rm 。(Git) - Git公式ドキュメント:
git check-ignore(どのルールに一致したかをデバッグ表示)
https://git-scm.com/docs/git-check-ignore 。(Git) - Pro Git(公式Book):Gitの変更管理と無視ファイルの基礎(Ignoring Filesの解説を含む章)
https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository 。(Git) - Pro Git(公式Book):グローバル無視
core.excludesfileの設定
https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration 。(Git) - GitHub Docs:Ignoring files(
.gitignoreの基本と共有ルール)
https://docs.github.com/articles/ignoring-files 。(GitHub Docs) - Atlassian Git Tutorial:
.gitignoreの使い方(ローカル/グローバル/.git/info/excludeの整理)
https://www.atlassian.com/git/tutorials/saving-changes/gitignore 。(atlassian.com) - BFG Repo-Cleaner(履歴からの機密・巨大ファイルの除去に)
https://rtyley.github.io/bfg-repo-cleaner/ 。(rtyley.github.io) - git-filter-repo(Git公式が
filter-branchの代替として推奨する履歴書き換えツール)
https://github.com/newren/git-filter-repo 。(github.com)

コメント