.git/info/exclude とは?自分だけ無視する書き方と .gitignore との違い

PR
.git/info/exclude とは?自分だけ無視する書き方と .gitignore との違い
この記事は約12分で読めます。

.git/info/exclude に書いたパターンは、そのリポジトリの、自分の手元だけで無視されます。コミットされないので、clone した人には配られません。手元で clone してみると、元のリポジトリの .git/info/exclude の行は、clone した先では効きませんでした。

書き方は .gitignore と同じです。手元で git init したリポジトリには、最初から # で始まる 6 行(コメント)が入っていて、自分の行はその下に足します。先頭の / は、リポジトリの根(リポジトリのいちばん上のフォルダ)を指します。根で次のコマンドを実行すると、notes.md を無視する行を足せます(エディタで .git/info/exclude を開いて書いてもよい、と GitHub の文書は書いています)。

printf 'notes.md\n' >> .git/info/exclude

優先は .gitignore より低く、.gitignore の行が勝ちます。すでに追跡している(Git が変更を記録している)ファイルには効きません。同じリポジトリにつないだ worktree(同じリポジトリを別のフォルダにもう一つ開く機能)では、同じ .git/info/exclude が共有されます。

この記事の出力は、Docker の Linux の Git 2.54.0 のものです。手元の Mac の Git 2.39.3(Apple Git-145)でも同じでした(2026年10月23日。最新の 2.56.0 と Windows では試していません)。出力に出るパスの頭は省きました(… で示しています)。

この記事でわかること
  • .git/info/exclude とは何か、.gitignore・グローバルの設定とどう違うか
  • 無視するかを決めるときの優先の順(4 段)と、手元で確かめた結果
  • 書く場所、最初から入っている行、1 行足して git check-ignore で確かめる方法
  • 書いたのに効かないとき(追跡中のファイル・.gitignore の行に負ける)
  • clone では配られず、worktree では共有されること

.git/info/exclude とは?

Git の文書は、無視するパターンをどのファイルに置くかは、使い方で決まると書いています。.git/info/exclude は、そのリポジトリだけの、ほかのリポジトリと共有しなくてよいものを書く場所です。GitHub の文書は、エディタが作るファイルのように、ほかの人は作らないと思う手元のファイルに使う、と説明しています。

.gitignore・グローバルとの違い

文書が挙げる 3 つの置き場を並べると、次のとおりです。

.gitignore.git/info/excludecore.excludesFile で指すファイル
置き場リポジトリの中(根のほか、下のフォルダにも置ける)リポジトリの .git の中の info/exclude設定 core.excludesFile で指すファイル。設定しないときの既定は ~/.config/git/ignore
共有されるかコミットすると、clone で配られるコミットされず、clone でも配られないリポジトリには入らない。既定の ~/.config/git/ignore を使うときは、設定は要らない
文書が挙げる使い道全員が無視したいものそのリポジトリだけの、ひとりの作業のやり方で出る補助のファイルどんなときも無視したいもの(使っているエディタのバックアップや一時ファイル)
優先高い真ん中低い

どのリポジトリでも無視したいもの(グローバル)の書き方は、.gitignore をグローバルに設定する方法にまとめました。

優先の順

Git の文書は、無視するかを決めるとき、複数の元を、次の優先の高い順に見ると書いています。同じ段の中では、最後に当たった行が結果を決めます。

  1. コマンドラインで渡したパターン(渡せるコマンドだけ)
  2. そのパスと同じフォルダか、親のフォルダ(作業ツリー〔手元のファイルを置いているフォルダ〕の根まで)の .gitignore。下のフォルダの .gitignore の行が、上のフォルダの行に勝ちます
  3. .git/info/exclude
  4. 設定 core.excludesFile のファイル

手元で、2 が 3 にも 4 にも勝つことを確かめました(3 と 4 の間は試していません)。.gitignore と .git/info/exclude に次の行を書き、core.excludesFile は ~/.gitignore_global(中身は *.swp の 1 行)に向けてあります。

$ cat -n .gitignore
     1	!keep.swp
     2	*.tmp
$ cat -n .git/info/exclude
     1	# git ls-files --others --exclude-from=.git/info/exclude
     2	# Lines that start with '#' are comments.
     3	# For a project mostly in C, the following would be a good set of
     4	# exclude patterns (uncomment them if you want to use them):
     5	# *.[oa]
     6	# *~
     7	notes.md
     8	!x.tmp
     9	/root-only.txt
$ git check-ignore -v -n a.swp keep.swp x.tmp y.tmp notes.md root-only.txt sub/root-only.txt
…/home/.gitignore_global:1:*.swp	a.swp
.gitignore:1:!keep.swp	keep.swp
.gitignore:2:*.tmp	x.tmp
.gitignore:2:*.tmp	y.tmp
.git/info/exclude:7:notes.md	notes.md
.git/info/exclude:9:/root-only.txt	root-only.txt
::	sub/root-only.txt

出力は「元のファイル:行番号:パターン」、タブ、パスの順です。読み方は .gitignore の書き方の確かめ方の節に書きました。ここで見るのは次の 2 つです。

  • .gitignore の *.tmp は、.git/info/exclude の !x.tmp に勝ちました。x.tmp は .gitignore:2:*.tmp に当たり、無視のままです。優先の高い .gitignore の行が決めたことになります
  • .gitignore の !keep.swp は、core.excludesFile の *.swp に勝ちました。keep.swp は ! の行(.gitignore:1:!keep.swp)に当たっていて、無視されません。a.swp だけが、core.excludesFile の行に当たっています

この出力は、手元の 2 つの版(Git 2.54.0 と 2.39.3)で同じでした。

文書には、3 の場所の書き方が版で違う、という点もあります。Git 2.34.0 から 2.54.0 の文書は $GIT_DIR/info/exclude、2.55.0 の文書からは $GIT_COMMON_DIR/info/exclude です。書き方が変わっただけで、動きは 2.39.3 でも同じでした(worktree の節で確かめます)。

どう書く?

場所と、最初から入っている行

GitHub の文書は、リポジトリの根の .git/info/exclude をエディタで開いて書くよう説明しています。ここに書いた規則はコミットされず、自分の手元のリポジトリだけで効きます。

手元で git init したリポジトリの .git/info/exclude は、次のとおりでした。1 行目から 6 行目は、最初から入っていた # で始まる行(コメント)で、7 行目が足した行です。最初の 6 行は、手元の 2 つの版で同じ文字でした。中身がどこから来るのかは、確かめていません。

$ cat -n .git/info/exclude
     1	# git ls-files --others --exclude-from=.git/info/exclude
     2	# Lines that start with '#' are comments.
     3	# For a project mostly in C, the following would be a good set of
     4	# exclude patterns (uncomment them if you want to use them):
     5	# *.[oa]
     6	# *~
     7	notes.md

1 行足して、git check-ignore で確かめる

git check-ignore -v は、パスが無視されるかを調べ、当たったパターンの元のファイルと行番号を出します。足したあとに notes.md を作って調べると、.git/info/exclude:7:notes.md と出ました。.git/info/exclude は根からの相対で出ます。最初の 6 行がコメントなので、足した行は 7 行目です。git status には notes.md が出ません(main.txt は無視していないので出ます)。

$ touch notes.md
$ git status --short --untracked-files=all
?? main.txt
$ git check-ignore -v notes.md
.git/info/exclude:7:notes.md	notes.md

-n を付けると、どの行にも当たらないパスも :: の形で出ます(上の優先の順の出力の最後の行)。

先頭の / はリポジトリの根

文書は、作業ツリーの外にある元(.git/info/exclude と core.excludesFile)のパターンは、リポジトリの根(作業ツリーのいちばん上のフォルダ)に書いたものとして扱うと書いています。先頭の / は、その根を指すということです。この段落は 2.54.0 の文書から入りました。

手元でも、上の優先の順の出力のとおりでした。.git/info/exclude の 9 行目の /root-only.txt は、根の root-only.txt に当たり、sub/root-only.txt には当たりませんでした(:: の行)。手元の 2 つの版で同じでした。

書いたのに効かないのはなぜ?

追跡中のファイルには効かない

すでに Git が追跡しているファイルには、.gitignore と同じく、.git/info/exclude も効きません。memo.txt をコミットしたあと、.git/info/exclude の最後に memo.txt を足して、memo.txt に 1 行足すと、次のようになりました。

$ tail -n 1 .git/info/exclude
memo.txt
$ git status --short
 M memo.txt
$ git check-ignore -v memo.txt
$ git check-ignore -v --no-index memo.txt
.git/info/exclude:7:memo.txt	memo.txt

git status --short には、変更された追跡中のファイルとして memo.txt が出続けました。git check-ignore -v memo.txt は何も出さず、終了コード(コマンドが返す数)は 1 です。インデックス(索引。次のコミットの候補)を見ない --no-index を付けると、.git/info/exclude の 7 行目に当たると分かります。追跡をやめる方法は .gitignore が反映されない・効かない原因と直し方に書きました。

.gitignore の行に負けている

.git/info/exclude の行は、優先の高い .gitignore の行に負けます。上の出力では、.git/info/exclude に !x.tmp と書いても .gitignore の *.tmp が勝ち、x.tmp は無視のままでした(.gitignore:2:*.tmp)。git check-ignore -v で、当たった行が .gitignore のどの行かを見ます。

clone や worktree ではどうなる?

clone では配られない

GitHub の文書は、.git/info/exclude に書いた規則はコミットされず、自分の手元のリポジトリだけで効くと書いています。手元でも、.git/info/exclude に notes.md を書いたリポジトリ(フォルダ名 e)を clone して、clone した先(e2)に notes.md と a.swp を作ると、notes.md は無視されませんでした。コミットした .gitignore は、clone で配られます。

$ git status --short --untracked-files=all
?? notes.md
$ git check-ignore -v -n notes.md a.swp
::	notes.md
…/home/.gitignore_global:1:*.swp	a.swp

notes.md は ::(どの行にも当たらない)です。a.swp が当たっているのは、このコンピューターの全体の設定(core.excludesFile)の行で、clone で来たものではありません。

worktree では共有される

2.55.0 の文書の直しは、.git/info/exclude は、同じリポジトリにつないだ worktree で共有される、と書いています。動きは前から同じで、文書が後から書いたものです。手元の 2 つの版で同じでした。e で git worktree add ../wt を実行し、wt に notes.md を作ると、次のようになりました。cat .git は、worktree の .git がフォルダではなくファイルで、元のリポジトリの中の場所を指していることを見せるためです。

$ cat .git
gitdir: …/e/.git/worktrees/wt
$ git status --short --untracked-files=all
$ git check-ignore -v notes.md
…/e/.git/info/exclude:7:notes.md	notes.md

git status --short は何も出さず、notes.md は無視されました。worktree の中では、.git/info/exclude が絶対パス(/ から始まる全部のパス)で出ます(元のリポジトリの e の .git/info/exclude が当たっています)。worktree の使い方は git worktree とは?にまとめました。

よくある質問

.gitignore とどちらに書けばいいですか?

全員が無視したいものは、.gitignore に書いてコミットします。clone した人にも配られるからです。そのリポジトリだけの、ほかと共有しなくてよいもの(ひとりの作業のやり方で出る補助のファイル)は、.git/info/exclude です。どちらも文書が挙げている使い分けです。書き方そのものは、どちらも同じです(.gitignore の書き方)。

.gitignore そのものを、自分だけ無視したいときは?

自分だけの規則は、.git/info/exclude に書きます。ただし、.gitignore がすでにコミットされていれば、.gitignore は追跡中のファイルなので、.git/info/exclude に書いても効きません(上の「追跡中のファイルには効かない」と同じです)。追跡をやめる前に、.gitignore が反映されない・効かない原因と直し方の「pull した人の手元からは消える」を読んでください。

全部のリポジトリで無視したいときは?

core.excludesFile で指すファイルに書きます。設定しなくても、~/.config/git/ignore は読まれます。書き方は .gitignore をグローバルに設定する方法にまとめました。

まとめ

  • .git/info/exclude は、そのリポジトリの、自分の手元だけで効く無視の規則を書く場所。コミットされず、clone でも配られない
  • 書き方は .gitignore と同じ。最初から入っている 6 行はコメントで、その下に足す。先頭の / はリポジトリの根
  • 優先は、コマンドラインのパターン、.gitignore、.git/info/exclude、core.excludesFile の順。.gitignore の行が勝つ
  • 追跡中のファイルには効かない。git check-ignore -v で、.git/info/exclude:7:… のように、どの行に当たったかを見る
  • 同じリポジトリの worktree では共有される
  • この記事で確かめていないこと: 最初の 6 行の出どころ、Windows、VS Code などの画面、最新の 2.56.0

参考資料

※この記事は、2026年10月23日時点の公式の資料と照らして確かめています。誤りに気づいたらお問い合わせからお知らせください。

PR
PR
タイトルとURLをコピーしました