.gitignore の書き方:* ** / ! の意味と、フォルダ・ワイルドカードの指定

PR
.gitignore の書き方:* ** / ! の意味と、フォルダ・ワイルドカードの指定
この記事は約17分で読めます。

.gitignore には、1 行に 1 つのパターン(無視するファイル名を表す書き方)を書きます。# で始まる行はコメント、空行は区切りです。/ が先頭か途中にあれば、その .gitignore の場所から数え、無ければどの階層にも当たります。

記号の意味は、次のとおりです。例は、そのあとの枠のとおりです(手元の確かめで使った行です)。

  • 末尾の /: フォルダにだけ当たります
  • *: / 以外の何にでも当たります
  • ?: / 以外の 1 文字に当たります
  • **: 階層をまたいで当たります
*.log
build/
/TODO
doc/*.txt

困ったときは、困りごとに合う記事に進みます。

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

この記事でわかること
  • 基本の決まり(1 行に 1 つのパターン・#・空行・行末の空白)
  • 記号ごとの意味(*・?・**・/・!・\)
  • フォルダの指し方と、/ の位置による当たり方の違い
  • 書いたあと、git check-ignore -v で確かめる方法(終了コードの読み方も)

.gitignore の書き方は? 基本の決まり

.gitignore は、Git に「わざと追跡しないファイル」を無視させるためのファイルです。次の決まりがあります。

  • 空の行は何にも当たらないので、読みやすくする区切りに使えます
  • # で始まる行はコメントです。# で始まる名前のファイルを無視したいときは、先頭の # の前に \ を付けます
  • 行の終わりの空白は、\ を付けて引用したもの以外は無視されます(引用した形は、この記事では試していません)
  • / はフォルダの区切りです。先頭か途中に / があるパターンは、その .gitignore のある場所からの相対になります。どこにも / が無ければ、その下のどの階層にも当たります

Pro Git は、新しいリポジトリでは、始める前に .gitignore を用意しておくとよい、と書いています。入れたくないファイルをうっかりコミットしないためです。

記号の一覧

記号の意味と、手元の結果を表にまとめます。意味は、Git の gitignore の文書のものです。手元の結果は、表の下の出力で確かめたものです。

記号意味例手元の結果
#行の頭に置くとコメント。名前が # で始まるときは \#\#hash.txt#hash.txt に当たった
*/ 以外の何にでも当たる*.logdebug.log・src/debug.log に当たった
?/ 以外の 1 文字file?.txtfile1.txt に当たり、file10.txt には当たらなかった(* と ** の節の出力)
[ ]範囲の中の 1 文字*.[oa]main.o・lib.a に当たった
**階層をまたいで当たるtmp/**・doc/**/*.pdftmp/x/b.txt・doc/x/y/b.pdf に当たった
/(先頭)その .gitignore の場所から数える/TODOTODO に当たり、src/TODO には当たらなかった
/(末尾)フォルダにだけ当たるbuild/build/out.js・src/build/gen.js に当たり、ふつうのファイル other/build には当たらなかった
/(途中)その .gitignore の場所から数えるdoc/*.txtdoc/notes.txt に当たり、doc/server/arch.txt(* は / に当たらない)・sub/doc/notes.txt(doc/ が根〔リポジトリのいちばん上のフォルダ〕の直下ではない)には当たらなかった
!前の行で除外されたものを、また含める!keep.logkeep.log は無視されなかった(*.log のあとに書いた)
\次の文字をそのままの文字にする\!important.txt!important.txt に当たった

\*(* そのもの)や、末尾の \ が何にも当たらないことは、文書に書かれていますが、この記事では試していません。

次の .gitignore(11 行)を書き、ファイルを 20 個作って(中身はどれも x)調べた出力です。other/build は、build という名前のふつうのファイルです。

$ cat -n .gitignore
     1	# comment: this line matches nothing
     2	*.log
     3	!keep.log
     4	/TODO
     5	build/
     6	doc/*.txt
     7	doc/**/*.pdf
     8	*.[oa]
     9	tmp/**
    10	\#hash.txt
    11	\!important.txt
$ git status --short --untracked-files=all
?? .gitignore
?? doc/server/arch.txt
?? hello.txt
?? keep.log
?? other/build
?? src/TODO
?? sub/doc/notes.txt
$ git check-ignore -v -n build/out.js src/build/gen.js other/build TODO src/TODO debug.log src/debug.log keep.log doc/notes.txt doc/server/arch.txt sub/doc/notes.txt doc/a.pdf doc/x/y/b.pdf main.o lib.a '#hash.txt' '!important.txt' tmp/a.txt tmp/x/b.txt hello.txt
.gitignore:5:build/	build/out.js
.gitignore:5:build/	src/build/gen.js
::	other/build
.gitignore:4:/TODO	TODO
::	src/TODO
.gitignore:2:*.log	debug.log
.gitignore:2:*.log	src/debug.log
.gitignore:3:!keep.log	keep.log
.gitignore:6:doc/*.txt	doc/notes.txt
::	doc/server/arch.txt
::	sub/doc/notes.txt
.gitignore:7:doc/**/*.pdf	doc/a.pdf
.gitignore:7:doc/**/*.pdf	doc/x/y/b.pdf
.gitignore:8:*.[oa]	main.o
.gitignore:8:*.[oa]	lib.a
.gitignore:10:\#hash.txt	#hash.txt
.gitignore:11:\!important.txt	!important.txt
.gitignore:9:tmp/**	tmp/a.txt
.gitignore:9:tmp/**	tmp/x/b.txt
::	hello.txt

出力は「元のファイル:行番号:パターン」、タブ、パスの順です。たとえば .gitignore:5:build/ build/out.js は、「.gitignore の 5 行目の build/ が、build/out.js に当たった」という意味です。パターンが ! で始まる行(.gitignore:3:!keep.log)に当たったときは、「無視しない」という意味です。:: は、どの行にも当たらなかったパスです(-n を付けたときだけ出ます)。git status --short の ?? は、Git がまだ追跡していないファイルで、ここに出ているのは無視されなかったファイルです。

フォルダを無視するには?(末尾の /)

パターンの末尾に / を置くと、フォルダにだけ当たります。文書の例では、foo/ はフォルダ foo とその下に当たり、foo という名前のふつうのファイルやシンボリックリンクには当たりません。doc/frotz/ は doc/frotz に当たり、a/doc/frotz には当たりません。frotz/ は frotz と a/frotz(フォルダ)に当たります。

上の出力でも、build/ は build/out.js と src/build/gen.js に当たり(.gitignore:5:build/)、build という名前のふつうのファイル other/build には当たりませんでした(::)。

foo/* のように末尾に * を付けると、別の決まりになります。文書の例では、foo/* は foo/test.json(ファイル)と foo/bar(フォルダ)に当たり、foo/bar/hello.c には当たりません。* は / に当たらないので、bar/hello.c には当たらないからです。この違いが、! で中の 1 つだけを戻すときに効きます(除外の除外の記事)。

/ の位置で、当たる場所はどう変わる?

/ が先頭か途中にあるパターンは、その .gitignore のある場所からの相対です。無ければ、その下のどの階層にも当たります。たとえば、/ が無い *.log は下の階層にも当たり、先頭に / がある /TODO は根の TODO だけに当たります。上の出力では、次のようになりました。

  • /TODO は TODO だけに当たり、src/TODO には当たりません
  • doc/*.txt は doc/notes.txt だけに当たり、sub/doc/notes.txt には当たりません
  • *.log(/ が無い)は、src/debug.log にも当たります

文書の例では、hello.* は名前が hello. で始まるファイルかフォルダに当たります。根のフォルダだけにするなら /hello.* と書きます。また、途中に / があれば先頭の / は関係ないので、doc/frotz と /doc/frotz は同じ意味です。hello.* は、この記事では試していません。

* と ** の違いは?

* は / 以外の何にでも当たります。**(アスタリスク 2 つ)は、パターンをパス全体と照らすとき、次のように扱われます(特別な意味を持つのは前の 3 つで、4 つ目はふつうの * です)。

  • 先頭の **/ は、どのフォルダの中でも当たります。**/foo は foo と同じ意味です
  • 末尾の /** は、中の全部に、深さを問わず当たります
  • /**/ は、0 個以上のフォルダに当たります。a/**/b は a/b・a/x/b・a/x/y/b に当たります
  • ほかの連続した * は、ふつうの * として扱われます

別のリポジトリで、次の .gitignore(4 行)を書き、ファイルを 8 個作って調べました。4 行目は、space.txt のあとに半角の空白が 2 つ付いています(行末の空白は無視されます)。

$ cat -n .gitignore
     1	**/cache
     2	a/**/b
     3	file?.txt
     4	space.txt  
$ git status --short --untracked-files=all
?? .gitignore
?? file10.txt
$ git check-ignore -v -n cache/c1 src/cache/c2 a/b a/x/b a/x/y/b file1.txt file10.txt space.txt
.gitignore:1:**/cache	cache/c1
.gitignore:1:**/cache	src/cache/c2
.gitignore:2:a/**/b	a/b
.gitignore:2:a/**/b	a/x/b
.gitignore:2:a/**/b	a/x/y/b
.gitignore:3:file?.txt	file1.txt
::	file10.txt
.gitignore:4:space.txt	space.txt

**/cache は cache/c1 と src/cache/c2 に、a/**/b は a/b・a/x/b・a/x/y/b に当たりました。file?.txt は file1.txt(1 文字)に当たり、file10.txt(2 文字)には当たりません。上の記号の一覧の出力では、tmp/** が tmp/a.txt と tmp/x/b.txt に、doc/**/*.pdf が doc/a.pdf と doc/x/y/b.pdf に当たりました。**/foo/bar の形は、この記事では試していません。

! で除外を取り消す

先頭が ! のパターンは否定で、前の行で除外されたファイルを、また含めます。同じ段の中では、最後に当たった行が結果を決めるので、!keep.log は *.log のあとに書きます(上の出力の .gitignore:3:!keep.log)。順番を逆にしたときは、除外の除外の記事にまとめました。

名前が ! で始まるファイルは、先頭の ! の前に \ を付けます(上の \!important.txt)。

親のフォルダを除外していると、その中のファイルは ! で戻せません。Git は、性能のために、除外したフォルダの中を見ないからです。戻し方は、除外の除外の記事にまとめました。

書いたら、どう確かめる?(git check-ignore -v)

git check-ignore は、渡したパスが無視されるかを調べ、無視されるならそのパスを出します。-v を付けると、当たったパターンの元のファイルと行番号も出ます。! で始まるパターンに当たったときは、「無視されない」という意味です。

次の出力は、根の .gitignore(*.log と build/)と、sub/.gitignore(!keep.log と /local.txt)、.git/info/exclude の 7 行目に足した notes.md で調べたものです。

$ cat -n .gitignore
     1	*.log
     2	build/
$ cat -n sub/.gitignore
     1	!keep.log
     2	/local.txt
$ git check-ignore debug.log main.txt
debug.log
$ git check-ignore main.txt
$ git check-ignore -v debug.log sub/other.log sub/keep.log sub/local.txt local.txt notes.md build/out.js
.gitignore:1:*.log	debug.log
.gitignore:1:*.log	sub/other.log
sub/.gitignore:1:!keep.log	sub/keep.log
sub/.gitignore:2:/local.txt	sub/local.txt
.git/info/exclude:7:notes.md	notes.md
.gitignore:2:build/	build/out.js
$ git check-ignore sub/keep.log

-v を付けないと、無視されるパスだけが出ます(1 つ目は debug.log だけ)。local.txt は、sub/.gitignore の /local.txt が sub/local.txt にだけ当たるので、-v でも出ません。sub/keep.log は、sub/.gitignore の !keep.log が根の *.log に勝って、無視されません。

終了コードの読み方

終了コード(コマンドが返す数)について、文書は、0 が「渡したパスのどれかが無視される」、1 が「どれも無視されない」、128 が致命的なエラーです。上の出力では、git check-ignore main.txt と git check-ignore sub/keep.log(-v なし)は何も出さず、終了コードは 1 でした。

! の行に当たって、無視されないファイルを 1 つだけ調べると、-v を付けたときは行が出て、終了コードは 0 になります。-v を付けないと、何も出ず 1 です。次は、logs/* と !logs/keep.log を書いた別のリポジトリでの出力です。

$ cat -n .gitignore
     1	logs/*
     2	!logs/keep.log
$ git check-ignore -v logs/keep.log
.gitignore:2:!logs/keep.log	logs/keep.log
$ git check-ignore logs/keep.log

1 つ目の git check-ignore -v logs/keep.log は終了コード 0、2 つ目は 1 でした。手元の 2 つの版では同じでした。文書は 0 を「渡したパスのどれかが無視される」と書いているので、文書の言い方とは合いません。-v の終了コードだけで「無視されている」と決めずに、出た行のパターン(行番号のあと)が ! で始まるかを見ます。

-n・-q・まだ無いファイル

-n(--non-matching)を付けると、どのパターンにも当たらないパスも出ます(-v と一緒のときだけ意味があります)。-q は何も出さず、終了コードだけを返します。パスは 1 つしか渡せません。

$ git check-ignore -v -n debug.log main.txt local.txt
.gitignore:1:*.log	debug.log
::	main.txt
::	local.txt
$ git check-ignore -q debug.log main.txt
fatal: --quiet is only valid with a single pathname

-q debug.log は終了コード 0、-q main.txt は 1、2 つ渡した上の例は 128 でした。まだ作っていないファイルの名前でも調べられます(not-yet-made.log を調べると、.gitignore:1:*.log に当たり、終了コードは 0 でした)。

追跡しているファイルは、git check-ignore に出ません(除外の規則の対象ではないからです)。インデックス(索引。次のコミットの候補)を見ずに調べる --no-index の使い方は、反映されないときの記事にあります。

無視されているファイルの一覧

git status --short --ignored は、無視されたファイルを !! で出します。無視されたフォルダは 1 行にまとまり、--untracked-files=all を付けると、フォルダの中のファイルが 1 つずつ出ます。

$ git status --short --ignored
?? local.txt
?? sub/
!! build/
!! debug.log
!! notes.md
!! sub/local.txt
!! sub/other.log
$ git status --short --ignored --untracked-files=all
?? local.txt
?? sub/.gitignore
?? sub/keep.log
!! build/out.js
!! debug.log
!! notes.md
!! sub/local.txt
!! sub/other.log

?? sub/ は、未追跡のフォルダの中が 1 行にまとまっています。--untracked-files=all を付けると、その中の sub/.gitignore と sub/keep.log が出ます。

.gitignore はどこに置く?

.gitignore は、リポジトリの根のほか、下のフォルダにも置けます。下のフォルダの .gitignore の規則は、そのフォルダの下のファイルにだけ効きます。上の出力では、sub/.gitignore の /local.txt は sub/local.txt に当たり、根の local.txt には当たりませんでした(::)。

下のフォルダの .gitignore は、上のフォルダの .gitignore に勝ちます。上の出力では、根の *.log で無視されるはずの sub/keep.log が、sub/.gitignore の !keep.log で戻っています。

誰が無視したいかで、置き場を選びます。Git の文書は、次のように書いています。

  • 全員が無視したいもの(clone で配りたいもの)は、.gitignore に書いてコミットします
  • そのリポジトリだけの、ほかと共有しなくてよいものは、.git/info/exclude です。くわしくは .git/info/exclude の記事にあります。複数の置き場がぶつかったときの優先の順も、その記事にまとめました
  • どんなときも無視したいもの(使っているエディタのバックアップや一時ファイル)は、ふつうは ~/.gitconfig の core.excludesFile で指すファイルに書く、と文書は書いています。設定しなくても、~/.config/git/ignore は読まれます。くわしくはグローバルの記事にあります

よくある質問

言語ごとのひな形(テンプレート)はありますか?

あります。GitHub は、よく使う OS・環境・言語の .gitignore の一覧を、github/gitignore のリポジトリで持っています。GitHub.com で新しいリポジトリやファイルを作るときの、ひな形を選ぶ欄にも、この一覧が使われています。GitHub CLI の manual には、gh repo gitignore list で一覧、gh repo gitignore view <名前> で中身を見られると書かれています(名前は大文字と小文字を区別します。gh repo gitignore view Go > .gitignore が manual の例で、新しく作るときの例です。いまの .gitignore は置き換わります)。この記事では、gh のコマンドは試していません。

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

.gitignore は、すでに Git が追跡しているファイルには効きません。追跡をやめる方法は、.gitignore が反映されない・効かない原因と直し方にまとめました。

.gitignore とは?

Git に、わざと追跡しないファイルを教えるファイルです。GitHub の文書は、リポジトリの根に作ること、clone する人と規則を共有するには、.gitignore をコミットすることを説明しています。.gitignore の説明から読みたいときは、.gitkeep と .gitignore の違いの記事もあります。

まとめ

  • .gitignore は 1 行に 1 つのパターン。# はコメント、空行は区切り
  • * は / 以外の何にでも、? は 1 文字、** は階層をまたぐ。末尾の / はフォルダにだけ、先頭か途中の / はその .gitignore の場所から数える
  • ! は除外の取り消し。同じ段では最後に当たった行が決める。親のフォルダを除外していると戻せない
  • 書いたら git check-ignore -v -n で、どの行に当たったかを見る。! の行に当たったときも -v の終了コードは 0 なので、出た行のパターン(行番号のあと)が ! で始まるかを見る
  • この記事で確かめていないこと: \ で守る行末の空白・\*・hello.*・**/foo/bar、大文字と小文字の区別、Windows、最新の 2.56.0

参考資料

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

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