.gitignore は、Gitに入れないファイルを書いておく一覧です。ただし、すでにコミットしたファイルには効きません。Gitはファイルの変更履歴を残す仕組みで、コミットは変更を履歴に1回分記録する操作です。この順番を知らずに .env を1行足して安心すると、鍵は履歴に残ったままになります。
ここでは小さな料理教室のリポジトリを例に、何を入れてはいけないか、どう書くか、書いたあとにどう確かめるかを順に動かして見せます。リポジトリは、ファイルと履歴をまとめて入れておく保管場所のことです。読み終わると、自分のリポジトリに .gitignore を置き、効いているかを自分で確かめられるようになります。
この記事の内容
先に答えると
.gitignore はリポジトリの一番上に置くテキストファイルで、1行に1つ、Gitに入れないファイルの名前や形を書きます。効くのはまだGitに入っていないファイルだけです。入ってしまったファイルは git rm --cached で管理から外しますが、それでも過去の履歴には残ります。鍵を入れてしまったなら、外すだけでは足りません。
- 入れてはいけないのは、
.env・鍵・パスワード、顧客の一覧、バックアップ、node_modules、大きなファイル、.DS_Storeです - 効いているかは
git check-ignore -v ファイル名とgit status --ignoredで確かめます git add .をやめて、ファイルを名指しで入れると事故が減ります- 最初の一式は GitHub のテンプレート集 github/gitignore から持ってきて、自社の分を足します
- 非公開リポジトリでも、招待した人には履歴まで全部見えます
リポジトリに入れてはいけないもの
サンプル料理教室には website(ホームページ)と reservation-mail(予約メールのスクリプト)の2つのリポジトリがあります。どちらも非公開です。それでも次のものは入れません。
| 入れないもの | 例 | 入れると困る理由 | 置き場所 |
|---|---|---|---|
| 鍵・パスワード | .env、秘密鍵のファイル | 手に入れた人がそのサービスを動かせる | パスワード管理ツール、サーバーの環境変数 |
| 顧客の一覧 | customers.csv、受講者名簿 | 個人情報が履歴に残り、見える人を絞れない | 予約システム、権限を絞った共有ドライブ |
| バックアップ | backup/、site-2026-10.zip | 鍵や顧客情報が混ざりやすく、大きい | リポジトリの外の保管場所 |
| 自動で作り直せるもの | node_modules | 量が多く、部品の一覧から作り直せる | 置かない |
| 大きなファイル | 教室の動画、撮影データ | 上限にかかり、履歴が重くなる | 共有ドライブ、動画サービス |
| OSのゴミ | .DS_Store | Macが勝手に作り、関係ない差分が増える | 置かない |
.env は、鍵やパスワードを書いておく設定ファイルの慣習的な名前です。node_modules は、JavaScriptの部品が入るフォルダです。ホームページを制作会社が作っていると見かけることがあります。
迷ったら「このファイルが外に出たら誰かに連絡することになるか」で考えます。連絡することになるものは入れません。実際に運用していると、困るのは鍵そのものより、調べるために書き出したCSVやバックアップの中に鍵や名簿が混ざっている場合です。名前で気づけないので、そもそもリポジトリのフォルダの中に置かない方が確かです。

書き方を動かして確かめる
練習用のフォルダに website を作り、入れていいものと入れてはいけないものを混ぜて置きました。.gitignore がないときの表示です。?? は、まだGitに入っていないファイルという印です。
$ git status --short --untracked-files=all
?? .DS_Store
?? .env
?? .env.example
?? .env.local
?? backup/readme.txt
?? backup/site-2026-10.zip
?? error.log
?? images/.DS_Store
?? images/logo.png
?? index.html
?? logs/mail.log
?? menu.html
?? node_modules/lib/index.js
?? style.css
この状態で git add . と打つと、全部入ります。そこで、フォルダの一番上に .gitignore という名前のファイルを作ります。
$ cat .gitignore
#鍵とパスワード
.env
.env.*
!.env.example
#ログ
*.log
#バックアップ
backup/
!backup/readme.txt
#自動で作られるもの
node_modules/
.DS_Store
.env.example は、鍵の値を入れず「どんな名前の鍵が要るか」だけを書いた見本です。これはGitに入れて共有したいので、! で例外にしました。もう一度見ると、一覧がここまで減ります。
$ git status --short --untracked-files=all
?? .env.example
?? .gitignore
?? images/logo.png
?? index.html
?? menu.html
?? style.css
.gitignore 自体はGitに入れます。入れておくと、クローン(リポジトリの複製)した人にも同じ規則が効きます。
書き方の一覧
下の表はすべて実際に動かして確かめたものです。
| 書き方 | 意味 | 当たるもの | 当たらないもの |
|---|---|---|---|
.env | この名前。どの階層でも | .env | .env.local |
.env.* | .env. で始まる名前 | .env.local | .env |
*.log | .log で終わる名前。どの階層でも | error.log、logs/mail.log | index.html |
backup/ | この名前のフォルダの中身全部 | backup/site-2026-10.zip | index.html |
/notes.txt | 一番上にあるものだけ | notes.txt | images/notes.txt |
images/*.psd | images の直下だけ | images/a.psd | images/raw/b.psd |
!.env.example | ここまでの除外を取り消す | .env.example | なし |
#説明 | コメント。行の先頭に書く | なし | なし |
効いているかを確かめる
書いただけで終わらせません。git check-ignore -v は、そのファイルがどの行で除外されたかを教えてくれます。
$ git check-ignore -v .env
.gitignore:2:.env .env
$ git check-ignore -v logs/mail.log
.gitignore:7:*.log logs/mail.log
$ git check-ignore -v images/.DS_Store
.gitignore:15:.DS_Store images/.DS_Store
$ git check-ignore -v index.html
読み方は「ファイル名:行番号:書いた規則、空白、調べたファイル」です。index.html は何も出ません。除外されていないという意味です。例外に当たったときは、規則の先頭に ! が付いて出ます。これは除外されていないという意味で、表示があるからといって除外ではありません。
$ git check-ignore -v .env.example
.gitignore:4:!.env.example .env.example
除外されているものを一覧で見るなら git status --ignored です。「Ignored files:」の下が、Gitが見ないことにしているものです。
$ git status --ignored
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.env.example
.gitignore
images/
index.html
menu.html
style.css
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
.DS_Store
.env
.env.local
backup/
error.log
images/.DS_Store
logs/
node_modules/
nothing added to commit but untracked files present (use "git add" to track)

! が効かない場合
さきほどの .gitignore には !backup/readme.txt と書きました。ところが、効いていません。
$ git check-ignore -v backup/readme.txt
.gitignore:10:backup/ backup/readme.txt
親のフォルダごと除外すると、中のファイルを ! で戻すことはできません。Git公式にもそう書かれています。残したいときは、フォルダではなく中身を除外する書き方に変えます。
$ cat .gitignore
backup/*
!backup/readme.txt
$ git check-ignore -v backup/site.zip
.gitignore:1:backup/* backup/site.zip
$ git check-ignore -v backup/readme.txt
.gitignore:2:!backup/readme.txt backup/readme.txt
順番にも意味があります。後ろの行が勝つので、! は除外の行より後に書きます。逆に書くと、例外が消えます。
$ cat .gitignore
!.env.example
.env*
$ git check-ignore -v .env.example
.gitignore:2:.env* .env.example
すでにコミットしたものを外す
ここが一番の落とし穴です。reservation-mail で、.gitignore を作る前に git add . をしてしまった場合を動かします。
$ git add .
$ git commit -m "予約メールのスクリプトを追加"
[main (root-commit) 5f1ec87] 予約メールのスクリプトを追加
2 files changed, 2 insertions(+)
create mode 100644 .env
create mode 100644 send_mail.py
あとから .env と書いた .gitignore をコミットし、.env の中身を変えてみます。
$ git status --short
M .env
$ git check-ignore -v .env
$ git check-ignore -v --no-index .env
.gitignore:1:.env .env
$ git ls-files
.env
.gitignore
send_mail.py
M は変更ありの印です。.gitignore に書いたのに、Gitは .env を追い続けています。git ls-files は、いまGitが管理しているファイルの一覧です。git check-ignore -v も何も返しません。--no-index を付けて初めて「規則としては当たっている」と分かります。
管理から外すのが git rm --cached です。--cached を付けると、Gitの管理からだけ外して、手元のファイルは消しません。
$ git rm --cached .env
rm '.env'
$ git status --short
D .env
$ git commit -m ".envをGitの管理から外す"
[main f8e4bb9] .envをGitの管理から外す
1 file changed, 1 deletion(-)
delete mode 100644 .env
$ ls -a
.
..
.env
.git
.gitignore
send_mail.py
$ git ls-files
.gitignore
send_mail.py
手元に .env は残り、Gitの一覧からは消えました。ここで安心すると危ないです。履歴を見ます。
$ git log --oneline
f8e4bb9 .envをGitの管理から外す
3138a85 .gitignoreを追加
5f1ec87 予約メールのスクリプトを追加
$ git log --oneline -- .env
f8e4bb9 .envをGitの管理から外す
5f1ec87 予約メールのスクリプトを追加
$ git show HEAD~2:.env
MAIL_API_KEY=xxxxxxxx-fake-key
git show HEAD~2:.env は「2つ前のコミットの .env を見せる」という意味です。外したあとでも、鍵はそのまま読めます(ここでの鍵は練習用の偽物です)。つまり git rm --cached はこれから先に入らなくするだけで、過去を消す操作ではありません。すでにGitHubへ送ってしまった鍵は、止めて作り直すところから始めます。
もう1つ、git rm --cached は他の人の手元に影響します。練習用に作った別のクローンで git pull(更新の受け取り)をすると、その人の .env は消えました。
$ ls -a
.
..
.env
.git
send_mail.py
$ git pull -q
$ ls -a
.
..
.git
.gitignore
send_mail.py
外注エンジニアBの手元で動かなくなる原因になるので、外したことと、.env を作り直してもらうことを先に伝えます。

git add . をやめて確かめる
git add . はフォルダの中の変更を全部入れる操作です。GitHubの公式の案内でも、git add . や git commit -a を避けてファイルを名指しすることが再発防止に挙げられています。.gitignore に書き忘れたファイルは、git add . で素通りします。
名指しで入れて、入るものを確かめる。流れはこれだけです。
git statusで変わったファイルを見ます。git add menu.htmlのように、入れるファイルを名指しします。git diff --cached --name-onlyで、次のコミットに入るファイルを見ます。git commit -m "料金表を修正"でコミットします。
どうしても git add . を使いたいときは、--dry-run を付けると、実際には入れずに「何が入るか」だけ出ます。
$ git add --dry-run .
add '.env.example'
add '.gitignore'
add 'images/logo.png'
add 'index.html'
add 'menu.html'
add 'style.css'
.gitignore は絶対の壁ではありません。-f を付けると、除外していても入ります。
$ git add -f .env
$ git status --short
A .env
git status の案内にも git add -f と出てくるので、AIや他の人が「これで入ります」と打ってしまうことがあります。実際に運用していると、AIに作業を手伝わせるときほどコミット前の一覧を人の目で見る価値があります。誤って入れたら、コミットする前に git restore --staged .env で戻せます。

テンプレートから始める
全部を自分で考える必要はありません。GitHubが github/gitignore というテンプレート集を公開しています。GitHub.comで新しいリポジトリを作るときに選べるテンプレートの元も、ここです。構成は3つに分かれています。
| 場所 | 中身 | 例 |
|---|---|---|
| 一番上 | よく使う言語・技術ごと | Python.gitignore、Node.gitignore |
Global | エディタ・ツール・OSごと | Global/macOS.gitignore(.DS_Store を含む) |
community | 主流ではない言語や道具ごと | 使うものがあれば |
reservation-mail はPythonのスクリプトなので Python.gitignore が合います。.env、.venv、__pycache__/ が入っています。Node.gitignore には node_modules/、.env、.env.*、!.env.example、*.log が入っています。
テンプレートに載らないのは会社固有のファイルです。customers.csv や backup/ は自分で足します。
全部のリポジトリに共通で効かせたいものは、自分のパソコンの ~/.config/git/ignore に書く方法もあります。.DS_Store のようにMacの人だけの事情は、ここに書く手もあります。逆に、自分だけで使うメモを除外したいなら、共有されない .git/info/exclude に書きます。
大きなファイルの上限と、データの置き場所
GitHubのファイルサイズの上限は次のとおりです(2026年11月時点)。
| 大きさ | 起きること |
|---|---|
| 25MiB超 | ブラウザからの追加はできない |
| 50MiB超 | GitHubから警告が出る。pushはできる |
| 100MiB超 | GitHubがブロックする |
| リポジトリ全体 | 1GB未満が理想、5GB未満を強く推奨 |
pushは手元の履歴をGitHubへ送る操作です。100MiBを超えるファイルをGitで追うなら、Git LFSという仕組みがあります。リポジトリには小さな目印のファイルだけを置き、本体を別の場所に保管します。
ただ、料理教室のような規模なら、ここまで要らないことがほとんどです。教室の動画や撮影データは、動画サービスや共有ドライブに置いて、ホームページからはリンクや書き出した画像だけを使えば足ります。Gitは「どこをどう変えたか」を読める文字のファイルに向いています。動画や大きな画像は差分が読めないうえ、一度コミットすると消しても履歴に残り、リポジトリが重いままになります。
非公開でも、招待した人には見える
顧客の一覧を入れてはいけない理由をもう少し具体的に書きます。非公開リポジトリは「誰にも見えない」という意味ではありません。招待した人には中身が履歴ごと見えます。外注エンジニアBを招待すれば、Bは過去のどのコミットでも開けます。Organization(会社用のアカウント)のオーナーは、組織全体を管理できます。
共同作業者から外しても、その人のパソコンにあるクローンは残ります。GitHub側からは消せません。
個人情報を入れないために、次の順で確かめます。
- リポジトリの「Settings」を開きます。
- サイドバーの「Access」にある「Collaborators」または「Collaborators & teams」を開きます。
- 名前が並んだ全員について、受講者の名簿を見せてよい相手かを考えます。
答えが1人でも「いいえ」なら、名簿はそのリポジトリに置けません。そもそも名簿は、ホームページの作業には要りません。作業の必要がない人にまで見える場所には置かない、で判断がつきます。

できないことと、その代わり
| できないこと | その代わり |
|---|---|
| すでに入ったファイルを無視する | git rm --cached で管理から外してから .gitignore に書く |
| 過去の履歴から消す | git filter-repo で履歴を書き換える。鍵なら先に止める |
| 他の人のクローンやフォーク(GitHub上の複製)から消す | 本人に消してもらうよう頼む。鍵は止めて作り直す |
| ファイルの中の1行だけ無視する | 鍵だけを .env に分け、そのファイルごと除外する |
| コードに直接書いた鍵を止める | 送る前に検査する道具 gitleaks を使う |
git add -f を止める | コミット前に一覧を見る習慣で補う |
.gitignore はファイルの名前と場所しか見ません。send_mail.py の中に鍵を直接書けば、そのままコミットできます。中身まで見るのは別の道具の仕事です。
よく詰まるところ
| 症状 | 原因 | 直し方 |
|---|---|---|
.gitignore に書いたのに M .env と出続ける | すでにコミットされている | git rm --cached .env のあとコミットする |
git check-ignore -v が何も返さないのに無視されない | 上と同じで、管理下のファイルは除外扱いにならない | git check-ignore -v --no-index .env で規則を確かめ、git ls-files で管理下か見る |
.env # 鍵のファイル と書いたら効かない | 行の途中の # はコメントにならず、名前の一部になる | コメントは別の行に書く |
! を書いたのに戻らない | 親のフォルダごと除外している | backup/ を backup/* に変える |
! を書いたのに例外にならない | ! の後ろに除外の行がある | 除外の行の後ろに ! を書く |
.env と書いたのに .env.local が入る | .env は完全に同じ名前にだけ当たる | .env.* を足し、見本は !.env.example で戻す |
.gitignore が全く効かない | .gitignore.txt など別の名前で保存している | 拡張子を外す。ls -a で名前を確かめる |
他の人の .env が git pull で消えた | git rm --cached のコミットを受け取ると、相手の手元では削除になる | 事前に伝え、消えた人は作り直す |
実際に動かすと、行末コメントの表示は次のようになります。.env が除外されず、未追加のファイルとして残っています。
$ cat .gitignore
.env # 鍵のファイル
$ git check-ignore -v .env
$ git status --short .env
?? .env
次に読む
鍵をすでに送ってしまったなら、「APIキーやパスワードをGitHubにpushしてしまったときの対応」を先に読みます。git add が何をしているかを整理するなら「git add・commit・pushの違い:保存して送るまでの流れ」です。誰に何が見えるかは「GitHubの権限と2段階認証:共同作業者・Organization・非公開リポジトリ」に、公開されている他人のリポジトリを使う前の見方は「GitHubのリポジトリの読み方:スター・ライセンス・READMEで導入前に見るところ」にまとめています。