解説
.gitignoreの例外が効かない?親フォルダと一致した行を調べよう
無視ルールの例外が効かないときは、親フォルダと一致した行を調べよう。検証用ファイルで-vの出力と!の意味を確認する。

生成ファイルを除外しつつ、同じフォルダの説明ファイルだけ残したい。ところが、! で例外を書いても候補に出ない。そんなときは、ルールを増やす前に、どの行が効いているかを調べよう。
今回は build/keep.txt を残し、build/cache.txt を除外する、小さな検証例を使う。実プロジェクトのファイルを消す操作は行わないよ。
まずは一致したルールの場所を読む
ターミナルでリポジトリのルートを開き、対象パスを指定する。
git check-ignore -v -- build/keep.txt
公式資料の -v は、パスだけでなく、ルールのファイル・行番号・パターンも表示する指定。ルールはルートの .gitignore 以外にもあるので、まず出力の先頭を確認しよう。
親を丸ごと除外した例
検証用リポジトリでは、次の二行をルートの .gitignore に置いた。build の中には keep.txt と cache.txt があり、どちらも未追跡、つまりまだGitの管理対象へ追加していない状態だよ。
build/
!build/keep.txt
先ほどのコマンドの結果は、次のとおり。
.gitignore:1:build/ build/keep.txt
出力のパターンとパスの間は実際にはタブ。ここでは見やすく空白で示している。
二行目ではなく、親フォルダを除外する一行目に当たっている。gitignoreの仕様では、親が除外されたまま、その中のファイルだけを再び含めることはできない。子の例外を後ろへ書くだけでは足りないんだ。
この例では、直下の中身を除外する
検証用の二行を、次のように置き換えた。
build/*
!build/keep.txt
build 自体を除外する形から、中身を対象にする形へ変えている。この例では keep.txt が直下にあるので、次の比較ができる。
git check-ignore -v -- build/keep.txt build/cache.txt
得られた結果は次の二行だった。
.gitignore:2:!build/keep.txt build/keep.txt
.gitignore:1:build/* build/cache.txt
ここで大事なのが !。詳細出力に名前が出たからといって、どちらも無視されているとは読まないでね。keep.txt の行には、除外を取り消すパターンが表示されている。
作業ツリーの状態も確認しよう。
git status --short --untracked-files=all
分離した検証用リポジトリのGit 2.54.0では、.gitignore と build/keep.txt が未追跡として表示され、build/cache.txt は表示されなかった。これが今回の目的に合う結果だよ。
この書き方を、深いフォルダ構造へそのまま流用しないことも大切。途中のフォルダが別のルールで除外されていないか、対象パスを一段ずつ確認しよう。
出力がない場合は、追跡状態も確認する
すでに追跡されているファイルは、通常の check-ignore の表示対象にならない。検証では keep.txt を追加したあと、通常の詳細表示が空になることも確かめた。
git ls-files -- build/keep.txt
git check-ignore --no-index -v -- build/keep.txt
--no-index は、追跡の有無による除外をせず、パターンを調べるための指定。追跡解除やファイル削除を行う指定ではないよ。通常の空出力だけで「設定が壊れた」と判断しないようにしたいね。
実プロジェクトでは、変更前のルールを控え、確認後に意図しない未追跡ファイルが増えていないかも読む。今回の練習を戻すなら、検証用 .gitignore を変更前の二行へ戻して結果を比べられる。ルールの確認だけを理由に、本物のファイルへ強制追加や削除をしないでね。
追跡済みファイルの扱いや秘密情報への対応は、.gitignoreと追跡済みファイルの違いで整理している。この記事は、その前後で「どのルールに当たったか」を調べるために使ってみよう。

みんなのコメント 0
感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。
最初のコメントをどうぞ。