APIキーやデータベースのパスワードが含まれた .env ファイルを誤ってGitにコミットし、さらにGitHubへプッシュしてしまった場合は、緊急対応が必要です。慌ててファイルを削除してコミットしても、git .env コミット 履歴には機密情報が完全に残っています。この記事では、リポジトリの履歴全体から .env ファイルを完全に抹消する手順を解説します。
注意
公開リポジトリに機密情報をプッシュした場合、悪意あるボットが数秒以内にAPIキーをスキャンして悪用します。下記の手順と並行して、漏洩したAPIキー・パスワードをすぐに無効化・再発行してください。
このシリーズの全記事
- 第1回:プログラミングエラーメッセージの読み方
- 第2回:VSCodeで「command not found: code」が出た時の解決方法
- 第3回:npmのEACCESエラーをsudoなしで安全に解決する方法
- 第4回:git commitでVimが開いたときにコミットをキャンセルする方法
- 第5回:git detached HEAD状態から安全に復帰する方法
- 第6回:git resetとgit revertの違いと使い分け
- 第7回:git restoreで特定のファイルだけを過去に戻す方法
- 第8回:VSCodeのマージエディタでgitコンフリクトを解消する手順
- 第9回:.envをGitにコミットしてしまった場合の履歴からの完全削除【この記事】
この記事でわかること
- ファイルを削除してコミットするだけでは機密情報が残る理由
- git filter-repoを使ってリポジトリ履歴全体から.envを抹消する手順
- 強制プッシュ後にチームメンバーへ伝えるべき対応事項
なぜgit rm –cachedだけでは不十分なのか
発覚後に最初に試みがちな対処として、以下のコマンドを実行する場合があります。
git rm --cached .env
git commit -m ".envを削除"
git push origin main
この操作は「最新のコミットのファイルツリーから .env を取り除く」ことはできます。しかし、Gitはすべての変更の履歴を保持しています。過去のコミット履歴を遡れば、.env を追加したコミットにはAPIキーが平文で残ったままです。
# 過去のコミットを指定してファイルの中身を確認できてしまう
git show abc1234:.env
# 出力:
DATABASE_PASSWORD=super_secret_password_123
API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
GitHubのAPIを使えば、プライベートリポジトリでも同様の方法でコミット履歴からファイルの中身を取得できます。
git filter-repoで履歴全体から完全に抹消する
git filter-repo はリポジトリの全コミット履歴を再構築するPython製のツールです(Git 2.29以降推奨)。かつて使われていた git filter-branch より大幅に高速で、現在は公式が推奨するツールです。
ステップ1:git filter-repoをインストールする
# macOS(Homebrewを使用)
brew install git-filter-repo
# 出力:
==> Installing git-filter-repo
==> Summary
/usr/local/Cellar/git-filter-repo/2.38.0: 3 files, 229.5KB
# pipを使う場合(Python 3.x環境)
pip install git-filter-repo
ステップ2:リポジトリをクリーンな状態にする
# 作業中の変更をすべてコミットまたは退避させる
git status
# 出力:
On branch main
nothing to commit, working tree clean
ステップ3:filter-repoで.envを全履歴から削除する
git filter-repo --path .env --invert-paths
# 出力:
Parsed 47 commits
New history written in 2.15 seconds; now repacking/cleaning...
Repacking your repo and cleaning out old unneeded objects
HEAD is now at def9876 最新のコミットメッセージ
Completely finished after 5.32 seconds.
--path .env で対象ファイルを指定し、--invert-paths で「そのファイルを含まないように」全コミットを再構築します。実行後、全コミット履歴から .env が存在しなくなります。
ステップ4:リモートに強制プッシュする
注意
以下の強制プッシュはリポジトリの全履歴を書き換えます。チームメンバーが存在する場合は、全員に事前に伝え、作業中の変更を退避するよう依頼してから実行してください。
git push origin --force --all
# 出力:
Enumerating objects: 38, done.
Counting objects: 100% (38/38), done.
Writing objects: 100% (38/38), 12.34 KiB | 12.34 MiB/s, done.
To github.com:user/repo.git
+ abc1234...def9876 main -> main (forced update)
ステップ5:チームメンバーへの対応依頼
強制プッシュ後、チームメンバーのローカルリポジトリは書き換えられた履歴と不整合になります。各メンバーに以下を実行するよう依頼してください。
# ローカルのブランチを削除して取り直す
git fetch origin
git reset --hard origin/main
再発防止:.gitignoreへの追記
恒久的な対策として、プロジェクトの .gitignore ファイルに .env を追記してください。これにより、今後 .env が誤ってステージングされることを防ぎます。
echo ".env" >> .gitignore
git add .gitignore
git commit -m ".envを.gitignoreに追加"
まとめ
git rm --cached .envでファイルを削除してコミットしても、過去の履歴には機密情報が残り続けるgit filter-repo --path .env --invert-pathsでリポジトリの全コミット履歴から.envを完全に抹消できる- 強制プッシュは全履歴を書き換えるため、事前にチームメンバーへの周知と、漏洩したAPIキー・パスワードの即時無効化・再発行を行うこと
シリーズナビゲーション:脱・初学者サバイバルガイド

コメント