やりたかったこと
git status を実行したら node_modules/ 以下のファイルが何千件も表示されて真っ赤になった。git add . するたびに重くなるし、pushしたらリポジトリが数百MBになってしまった。.gitignore で管理対象から外す方法を調べた。
環境
- OS: macOS 13.5 / Ubuntu 22.04
- Git: 2.42.0
- Node.js: 20.11.0
試したこと・うまくいかなかったこと
.gitignore を新しく作って node_modules/ と書いた。git status を確認したら、まだ node_modules の中身が表示されていた。
原因はすでに一度 git add していたからだった。.gitignore はgitのトラッキングに入っていないファイルを無視するものであって、すでにトラッキング済みのファイルには効かない。
次に、トラッキングを外せばいいと思って git rm -r node_modules/ を実行したら、ローカルのファイルまで消えてしまった。node_modules を削除してから npm install し直すハメになった。
解決策
.gitignoreファイルを作る
プロジェクトのルート(.git と同じ階層)に .gitignore を作る。
node_modules/
dist/
.env
.env.local
.astro/
*.log
.DS_Store
すでにトラッキング済みのファイルを管理から外す
.gitignore を追加しただけでは既存のトラッキングには効かない。git rm --cached でgitのインデックスからだけ削除する(ローカルのファイルは残る)。
# 特定のファイルをトラッキングから外す
git rm --cached .env
# ディレクトリごと外す
git rm -r --cached node_modules/
# インデックスへの変更をコミットする
git add .
git commit -m "remove node_modules and .env from tracking"
--cached を付けると、ローカルのファイルはそのままでgitの管理からだけ外れる。
テンプレートを使って生成する
https://www.toptal.com/developers/gitignore でOS・エディタ・言語を選ぶと自動生成できる。Node.js + macOS + VSCodeの組み合わせで生成したものをベースにして、プロジェクト固有のパスを追加するのが早かった。
特定のパターンだけ除外する書き方
# *.log は無視するが error.log は無視しない
*.log
!error.log
# ルート直下のTODO.txtのみ無視(サブディレクトリのは無視しない)
/TODO.txt
# buildディレクトリ以下を全て無視
build/
ハマったポイント
.gitignoreは「まだgitに追加されていないファイル」だけに効く。すでにコミット済みのファイルはgit rm --cachedで明示的に外さないといけなかった。これを知らずに「なぜ効かないんだ」と30分悩んだgit rm -r node_modules/とgit rm -r --cached node_modules/は全然違う。--cachedなしでやるとローカルのファイルが消える.envをコミットしてしまってGitHubにpushしたことがある。「削除してpushし直せばOK」ではなく、git historyに残るのでAPIキーやパスワードは必ず変更する.gitignoreの書き方はパターンに注意。node_modulesと書くとルート以外のサブディレクトリのnode_modulesも無視される。/node_modulesと書くとルート直下のみ。どちらでも大体の用途には問題ないが、モノレポ構成のときは注意が必要だったgit statusで除外されているはずのファイルが出てきたらgit check-ignore -v ファイルパスで.gitignoreのどのルールが当たっているか(または当たっていないか)確認できる
関連記事
- GitHubで初めてリポジトリを作ってpushする手順
- Gitで間違えてcommitした時の取り消し方
- GitのブランチをCLIで作成・切り替える基本コマンド
- GitHub Actionsで自動デプロイする基本的な設定方法