Stage 2・中級編 ー Lesson 2-4
.gitignore とは? 追跡しないファイルを決める
.gitignore に書いたファイルは Git の管理対象から除外される
💡 たとえるなら
玄関に「持って行かない物リスト」を貼っておいて、出かけるとき自動で除外する感覚
実際のプロジェクトには 「Gitに記録したくないファイル」 がたくさんあります。たとえばビルド成果物、ログファイル、エディタの設定、パスワードの入った設定ファイル。これらをいちいち除外するのは面倒なので、Gitには .gitignore という仕組みがあります。
こんなファイルは無視したい
| 種類 | 例 |
|---|---|
| ビルド成果物 | dist/, build/, *.o, *.class |
| 依存パッケージ | node_modules/, vendor/, __pycache__/ |
| ログ・一時ファイル | *.log, *.tmp, *.bak |
| OS が作るファイル | .DS_Store(Mac)、Thumbs.db(Windows) |
| エディタ設定 | .vscode/, .idea/ |
| 機密情報 | .env, credentials.json, *.pem |
これらをコミットしてしまうと「リポジトリが太る」「機密が流出する」「他の環境で壊れる」など、ろくなことがありません。
.gitignore の書き方
リポジトリの ルート直下 に .gitignore という名前のファイルを作って、無視したいパターンを1行ずつ書きます。
パターンのルール(glob パターン)
.gitignore のワイルドカードは glob(グロブ)パターン。覚えるルールは3つだけです:
/ の位置 で「どの階層にマッチするか」が決まる② 末尾の
/ で「フォルダ限定にするか」が決まる③ ワイルドカード(
* ** ? [abc] !)で「マッチする文字」が決まる
順番に見ていきます。
ルール①:/ があれば固定、無ければどこでも
ざっくり言うと:
| パターン | / の有無 | マッチする階層 |
|---|---|---|
name | 無し | どの階層でも(basename match) |
/name logs/name /logs/name | 有り(どこかに1つでも) | .gitignore の場所からの 相対パスで固定 |
ポイント:パターンに / が どこかに1つでもある と、その時点で「.gitignore 直下からの相対パス」になります。先頭の / が意味を持つのは、他に / が無いときだけ。
logs/nameと/logs/name→ 同じ(どちらも anchored、先頭/は冗長)nameと/name→ 違う(nameはどこでもマッチ、/nameは直下のみ)
例で確認:
| パターン | app.log(直下) | logs/app.log(直下のlogs) | a/b/logs/app.log(深い階層のlogs) |
|---|---|---|---|
app.log | ✅ | ✅ | ✅ |
/app.log | ✅ | ❌ | ❌ |
logs/app.log | ❌ | ✅ | ❌ ← logs が深いと当たらない |
/logs/app.log | ❌ | ✅ | ❌ ← 同上 |
ルール②:末尾 / で「フォルダ限定」になる
| パターン | 何にマッチ? |
|---|---|
tmp | 同名の ファイルもフォルダも 両方(フォルダなら中身も) |
tmp/ | フォルダだけ(同名ファイルがあっても残る) |
実用:「中身が必ずフォルダ」と分かっているもの(node_modules/、dist/、build/)は / を付けて意図を明確化するのが定番。
ルール③:ワイルドカード
| 記号 | 意味 | 例 |
|---|---|---|
* | / 以外の 0文字以上 | *.log → app.log、error.log |
? | 任意の1文字 | ?.txt → a.txt、1.txt |
[abc] | 候補から1文字 | [abc].txt → a.txt、b.txt、c.txt |
** | 0個以上のディレクトリ階層 | logs/**/*.log → logs/app.log、logs/sub/app.log |
! | 除外の除外(既に無視されてても追跡) | !keep.log |
ハマりどころ①:* と ** の違い
* は / をまたがない、** は またぐ。
| パターン | app.log | logs/app.log | logs/sub/app.log | a/logs/app.log |
|---|---|---|---|---|
*.log | ✅ | ✅ ※ | ✅ ※ | ✅ ※ |
/*.log | ✅ | ❌ | ❌ | ❌ |
logs/*.log | ❌ | ✅ | ❌ | ❌ |
logs/**/*.log | ❌ | ✅ | ✅ | ❌ |
**/logs/*.log | ❌ | ✅ | ❌ | ✅ |
※ *.log はパターン中に / が無いので ルール①が優先 され、basename match でどの階層でもマッチ。logs/*.log のように / を入れると path match になり、* の階層またぎ禁止が効く。
**/logs/*.log はよく使うパターン:「どの階層にある logs/ でも、その直下の .log だけ」を意味します。**/ で「logs まで何階層でも」を許し、最後の *.log で「logs の直下だけ(孫は対象外)」という挙動。
ハマりどころ②:dir と dir/** の違い
「フォルダの一部だけ追跡したい」ときに重要。
| 比較 | dir | dir/** |
|---|---|---|
| マッチ階層 | どの階層でも | ルート直下の dir/ のみ |
| dir フォルダの扱い | フォルダごと無視(中を見ない) | 中身を1つずつ無視 |
!keep.txt で例外を作れる? | ❌ できない | ✅ できる |
dir だと git が フォルダ自体を無視して中を覗かない ので、中の !keep.txt も評価されません。例外を作りたいときは必ず dir/**:
build/** !build/keep.txt
これで build/ の中身は無視しつつ、build/keep.txt だけ追跡できます。
チートシート
よく使うパターンをまとめると:
| やりたいこと | パターン |
|---|---|
すべての .log を無視 | *.log |
ルート直下の .env だけ無視 | /.env |
node_modules フォルダ丸ごと | node_modules/ |
build/ の中身を無視、keep.txt だけ追跡 | build/**!build/keep.txt |
logs/ 配下のすべての .log を再帰的に | logs/**/*.log |
Git には blob(ファイルの中身の塊)という別概念がありますが、これは内部のオブジェクト名で、
.gitignore のパターンとは無関係。正しくは glob(グロブ) パターンです。
.gitignore 自体は追跡する
.gitignore は 追跡対象 にしてコミットします。チームで共有することで、全員が同じ無視ルールを使えます。
やってみよう
my_project で実験。
today.log が status から消えたのが見えますか? これで以降、today.log は誤って add されません。
すでに追跡してしまったファイルを無視に切り替える
「.gitignore を書く前にうっかりコミットしてしまった」場合、.gitignore だけでは無視されません(既に追跡対象なので)。一度 Git の追跡から外す必要があります。
--cached がポイント。これがないとファイル本体まで消えるので注意。
グローバルな .gitignore
.DS_Store や .vscode/ みたいに 「自分の環境固有」 のものをチームの .gitignore に入れるのは少し気が引けます。そういうときは ホームディレクトリに置くグローバルな .gitignore が使えます:
これで全プロジェクトで自動的に無視されます。
言語別テンプレート
ゼロから書かなくても、GitHub が公開している 言語別の .gitignore テンプレート が便利です:
- github.com/github/gitignore — Node, Python, Java, Go, Rust など主要言語のテンプレ集
- gitignore.io — OS / IDE / 言語を選ぶと組み合わせて生成してくれる
新規プロジェクトを始めるときは、まずこのテンプレを .gitignore にコピペして、必要に応じて足し引きするのが定番です。
このレッスンのまとめ
.gitignore でファイルを追跡対象から除外できる*.log /dir/ !exception などのパターンが書けるgit rm --cached で追跡済みファイルを後から外せるcore.excludesfile で自分専用の無視ルールも持てる.gitignore が作れる✏️ 理解度チェック
各問題、選んだ瞬間に正解と解説が表示されます。気軽に試してください。
- Q1. .gitignore に書くべきファイルとして適切なのは?
- Q2. 「フォルダ全体を無視」したいときの書き方は?
- Q3. すでに git で追跡中のファイルを .gitignore に追加した。どうなる?