.envファイルをGitにコミットしてしまった場合の履歴からの完全削除手順【git filter-repo】

Git

APIキーやデータベースのパスワードが含まれた .env ファイルを誤ってGitにコミットし、さらにGitHubへプッシュしてしまった場合は、緊急対応が必要です。慌ててファイルを削除してコミットしても、git .env コミット 履歴には機密情報が完全に残っています。この記事では、リポジトリの履歴全体から .env ファイルを完全に抹消する手順を解説します。

注意

公開リポジトリに機密情報をプッシュした場合、悪意あるボットが数秒以内にAPIキーをスキャンして悪用します。下記の手順と並行して、漏洩したAPIキー・パスワードをすぐに無効化・再発行してください。

この記事でわかること

  • ファイルを削除してコミットするだけでは機密情報が残る理由
  • 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キー・パスワードの即時無効化・再発行を行うこと

シリーズナビゲーション:脱・初学者サバイバルガイド

関連記事

コメント

タイトルとURLをコピーしました