Git入門:バージョン管理のきほん
追跡しないファイルを決める(.gitignore)
この回でやること
.gitignore で Git に記録させないファイルを指定する方法を学びます。書き方のパターンと、一度コミットしたファイルが除外されない落とし穴の直し方まで身につけましょう。
- 読む 約 7 分
status が、自分で書いていないファイルで埋まる
プロジェクトのフォルダには、自分が書いたもの以外のファイルが次々に生まれます。npm install で入るライブラリ、ビルドの成果物、エディタの設定、macOS が置いていく .DS_Store。git status を打つと数万件の未追跡ファイルが流れて、肝心の自分の変更が見えなくなります。
このまま全部記録すると、もっと困ることが起きます。リポジトリが数百 MB に膨れ、自動生成物が変わるたびに何千行もの差分が出てレビューが読めなくなり、そして .env に書いた API キーがそのまま公開されます。
判断の基準は 1 つです。そのファイルは、他の人が同じ手順で作り直せるか。 node_modules は npm install で、dist はビルドで作り直せます。作り直せるものは記録しません。.env は作り直せませんが、公開してはいけないのでやはり記録しません。
書き方は 5 つ覚えれば足りる
リポジトリの一番上に .gitignore という名前のファイルを作り、1 行に 1 つ書きます。
プレーンテキスト
# 依存パッケージ
node_modules/
# ビルド成果物
dist/
# 環境変数
.env
# OS が作るファイル
.DS_Store
Thumbs.db
# ログ
*.log# の行はコメントです。macOS は .DS_Store、Windows は Thumbs.db を作るので、チームで OS が混ざるなら両方書いておきます。
書き方の決まりはこれだけです。
| 書き方 | 意味 |
|---|---|
secret.txt | どの階層でも、この名前を除外する |
/secret.txt | 一番上の階層にある 1 つだけを除外する |
logs/ | そのフォルダを中身ごと除外する |
*.log | 拡張子が .log のものを全部除外する |
!sample.log | 除外の対象から外す |
末尾のスラッシュの有無で意味が変わります。logs はファイルにも当たりますが、logs/ はフォルダだけに当たります。! は、まとめて除外したうえで例外を作るときに使います。あとに書いた行が優先されるので、*.log より前に !sample.log を書いても効きません。
.gitignore 自身はコミットします。チーム全員に同じ除外を効かせるための設定だからです。
一度コミットしたファイルには効かない
ここが最大の落とし穴です。.gitignore は、まだ追跡していないファイルにしか効きません。一度でもコミットしたファイルは、あとから書き足しても git status に出続けます。Git から見れば、それはもう登録済みのものだからです。
うっかり .env をコミットしてしまったときは、管理対象から降ろします。
ターミナル
$ git rm --cached .env
rm '.env'
$ git commit -m ".env を追跡対象から外す"--cached が付いていると、外れるのは登録だけで、手元のファイルは残ります。アプリはこれまで通り動きます。フォルダごと外すときは git rm -r --cached node_modules のように -r を足します。何万行も削除の一覧が流れますが、消えているのは登録だけです。
--cachedを書き落とすと、追跡から外すだけでなく実ファイルまで消えます。設定ファイルを失ってアプリが起動しなくなる事故がよく起きます。打つ前に、その 8 文字があるか目で確かめてください。
そして、追跡から外しても、過去のコミットの中には元の中身が残ります。公開リポジトリに鍵を送ってしまった場合、外しただけでは漏洩は止まりません。まずサービス側でその鍵を無効にし、新しい鍵を発行し直してください。履歴から消すより、そのほうが速くて確実です。
- 作り直せるものは記録しない。
.envは作り直せないが、公開できないのでやはり記録しない - 末尾のスラッシュはフォルダ限定、
*は総当たり、!は打ち消し。.gitignore自身はコミットする - 一度コミットしたものには効かない。
git rm --cachedで登録を外す