概要
APIキー、パスワード、秘密鍵などのセンシティブな情報を誤って Git リポジトリにコミット・プッシュしてしまった場合、単純に git rm してコミットするだけでは不十分です。Git の履歴にはすべての変更が記録されているため、過去のコミットを辿れば誰でも削除したつもりのファイルを参照できてしまいます。
この記事では、GitLab および GitHub から該当ファイルの履歴を物理的に削除する手順を解説します。
まず最初にやること 作業を始める前に、流出したクレデンシャルを今すぐ無効化・ローテーションしてください。削除作業中もそのクレデンシャルは有効なままです。完全な削除が完了するまでの間も攻撃者がアクセスできる状態が続きます。
GitLab 編
1. ツールのインストール
履歴書き換えには git-filter-repo を使用します。Git 公式も推奨しているツールで、旧来の git filter-branch より安全かつ高速です。
pip install git-filter-repo2. ミラークローンで全履歴を取得
git clone --mirror <リポジトリの URL>cd <リポジトリ名>.gitミラークローンとは?
通常の git clone はデフォルトブランチのみを取得しますが、--mirror オプションを付けるとすべてのブランチ・タグ・refs を含む完全なコピーが取得されます。作業ディレクトリは作成されず、.git の中身がそのままフォルダに展開された状態(ベアリポジトリ)になります。
履歴の書き換えはすべてのブランチに一括で適用する必要があるため、ミラークローンが必要です。
3. 対象ファイルの履歴を削除
git filter-repo --path <削除対象ファイルのパス> --invert-paths--path: 対象ファイルのパスを指定します(例:config/secrets.yml、src/.env)--invert-paths: 指定したパス以外を残す、つまり指定したファイルをすべての履歴から取り除く、という意味です
複数ファイルを一度に削除したい場合は --path を並べます:
git filter-repo --path config/secrets.yml --path .env --invert-paths実行後、すべてのコミット履歴からそのファイルが取り除かれます。
4. GitLab のプロテクトブランチを一時解除
強制プッシュ(force push)は通常、保護されたブランチへは禁止されています。GitLab の管理画面から一時的に解除します。
- GitLab のリポジトリページを開く
- Settings > Repository > Protected branches に移動
main、developなどの保護ブランチを Unprotect にする
作業終了後は必ず保護設定を元に戻してください。
5. リモートの登録と強制プッシュ
ミラークローンした状態ではリモートが未設定のため、まず追加します:
git remote add origin <リポジトリの URL>すべてのブランチとタグを強制プッシュします:
# 全ブランチの強制プッシュgit push origin --force --all
# 全タグの強制プッシュgit push origin --force --tags強制プッシュが必要な理由
通常のプッシュはリモートの履歴に対して追記のみが許可されています。今回は履歴を書き換えているため、リモートとローカルの履歴が矛盾します。--force を使うことでリモートの履歴を上書きします。
6. プロテクトブランチの保護設定を復旧
手順 4 で Unprotect したブランチを元の設定に戻します。
Settings > Repository > Protected branches から再設定してください。
7. GitLab 上の物理削除(ハウスキーピング)
強制プッシュでリモートから参照は外れますが、GitLab のサーバー上にはキャッシュや内部オブジェクトが残っている場合があります。ハウスキーピングを実行して物理的にデータを削除します。
- GitLab のリポジトリページを開く
- Settings > General > Advanced に移動
- Housekeeping(ハウスキーピング) を実行
GitLab.com(SaaS)の場合、完全な物理削除にはサポートへの問い合わせが必要になるケースもあります。セルフホスト版では管理者が
git gc --prune=nowを実行することでも対応できます。
8. 削除確認
対象ファイルへの古いコミットのパーマリンク URL にアクセスし、404 エラーが返ることを確認します。
例:
https://gitlab.com/<namespace>/<repo>/-/blob/<古いcommit hash>/<削除対象ファイルのパス>404 が返れば、GitLab 上からは閲覧不可能になっています。
GitHub 編
基本的な手順は GitLab と同様ですが、いくつか差異があります。
1〜3. ツールインストール・ミラークローン・履歴削除
GitLab と完全に同じ手順です。
pip install git-filter-repogit clone --mirror <リポジトリの URL>cd <リポジトリ名>.gitgit filter-repo --path <削除対象ファイルのパス> --invert-paths4. GitHub のブランチ保護ルールを一時解除
- GitHub のリポジトリページを開く
- Settings > Branches に移動
- Branch protection rules の対象ブランチ(
mainなど)の Edit をクリック - Require a pull request before merging などのルールを一時的に無効化するか、または Allow force pushes を有効にする
5. 強制プッシュ
git remote add origin <リポジトリの URL>git push origin --force --allgit push origin --force --tags6. ブランチ保護ルールの復旧
手順 4 で変更した設定を元に戻します。
7. GitHub のキャッシュ削除
GitHub 側のキャッシュやフォークには古いデータが残っている可能性があります。
- キャッシュのクリア: GitHub サポートへ問い合わせることで、サーバー側のキャッシュを削除してもらえます。
- フォークの扱い: フォークしているリポジトリには書き換えが反映されないため、フォーク先でも同様の作業が必要です。フォーク一覧は Settings > Danger Zone から確認できます。
GitHub には Secret scanning 機能があり、プッシュされたシークレットを自動検出してアラートを出してくれます。流出したシークレットのローテーションと合わせて活用してください。
チームメンバーへの周知とローカル環境の復旧
これが非常に重要です。 書き換えた履歴を他のメンバーがそのまま git push すると、削除したはずの履歴が復活してしまいます。必ずチーム全員に作業完了を通知し、ローカル環境を更新してもらってください。
絶対禁止: 作業完了前後に既存のローカルリポジトリから
git pushしないこと 古い履歴を持ったまま push すると、削除した情報が再びリモートに載ってしまいます。
未プッシュの変更がない人
一番シンプルなケースです。既存のフォルダを削除して再クローンするだけです。
# 既存のフォルダを削除rm -rf <リポジトリのフォルダ>
# 再クローンgit clone <リポジトリの URL>未プッシュの変更がある人
作業中の変更をパッチファイルに退避してから再クローンします。
# ステップ1: 現在の差分をパッチファイルに書き出すgit diff > my.patch
# ステップ2: ステージ済みの変更も含める場合git diff --cached >> my.patch
# ステップ3: 既存フォルダを削除して再クローンrm -rf <リポジトリのフォルダ>git clone <リポジトリの URL>cd <リポジトリのフォルダ>
# ステップ4: パッチを適用して変更を復元git apply my.patchブランチも含めた変更がある場合は、
git bundleを使うとより安全に移行できます。
まとめ・チェックリスト
| ステップ | 内容 |
|---|---|
| ✅ 0 | 流出したクレデンシャルを今すぐ無効化・ローテーション |
| ✅ 1 | git-filter-repo のインストール |
| ✅ 2 | ミラークローンで全履歴取得 |
| ✅ 3 | --invert-paths で対象ファイルを履歴から削除 |
| ✅ 4 | ブランチ保護の一時解除 |
| ✅ 5 | --force --all と --force --tags で強制プッシュ |
| ✅ 6 | ブランチ保護の復旧 |
| ✅ 7 | ハウスキーピング(物理削除) |
| ✅ 8 | 古い URL が 404 になることを確認 |
| ✅ 9 | チームメンバーへ周知・ローカル環境を再クローン |
そもそも防ぐためには .gitignore の徹底や git-secrets などのプリコミットフックの導入が有効です。「消す方法」を知ることも大事ですが、「プッシュしない仕組み」を先に整えることを強くお勧めします。
That’s all!