GithubとGitの履歴から誤ってPushしたファイルを完全に削除する方法
2024/07/21
プログラミングはじめに
GitHubにプッシュされた機密データは侵害されたとみなすべきである。パスワードや秘密鍵は破棄して新しく作成した方が良い。簡単に破棄、変更できないような機密データの場合は、次の「履歴情報を変更する」に従って履歴から抹消する。
履歴情報を削除する
1つ目は、ローカル環境で.gitディレクトリを削除した上で、新しく作成したGithubリポジトリに対象ディレクトリをプッシュする方法。.gitディレクトリに含まれるコミット履歴やブランチ情報はすべて失われてしまうが、簡単で確実。
2つ目は、ローカル環境でコミット履歴を書き換えて、新しく作成したGithubリポジトリに対象のディレクトリをプッシュする方法。コミット履歴を書き換えるだけなので、コミット履歴やブランチ情報は残るが、やや煩雑。
どちらの方法でも、GitHubリポジトリは新しく作成して乗り換える必要があるが、これはGitHub側に履歴が残っているため。詳しくは、後述の「force-pushしてもGitHub側に履歴が残る」を参照。
① .gitディレクトリを削除する方法
Githubリポジトリと同期して、ローカル環境を(機密データを含んでいない)最新状態にしておく。なければcloneする。
$ git clone https://github.com/<ユーザー名>/<旧リポジトリ名>.git
$ cd <リポジトリ名>
$ rm -rf .git
$ git init
$ git remote add origin https://github.com/<ユーザー名>/<新規リポジトリ名>.git
$ git remote -v # 確認
$ git add .
$ git commit -a -m "Initial Commit"
$ git push --force origin main
② コミット履歴を書き換える方法
Githubリポジトリと同期して、ローカル環境を(機密データを含んでいない)最新状態にしておく。なければcloneする。
$ git clone https://github.com/<ユーザー名>/<旧リポジトリ名>.git
$ cd <リポジトリ名>
まず、対象のファイル(path/to/secret)の存在を確認する。
$ git log --all --name-status --pretty=short --graph -- path/to/secret
すべてのコミットから対象のファイル(path/to/secret)を削除する。
$ git filter-branch --tree-filter 'rm -f path/to/secret' HEAD --all
上の操作で作成された不要なログファイルを削除する
$ rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --aggressive --prune=now
$ git remote rm origin
$ git remote add origin https://github.com/<ユーザー名>/<新規リポジトリ名>.git
$ git remote -v # 確認
$ git push --force origin main
force-pushしてもGitHub側に履歴が残る
force-pushで強制的にコミット履歴を書き換えても、GitHubリポジトリ側に履歴が残ってしまう。そのため、次のように直接コミットハッシュを指定すると、削除したつもりの履歴が見えてしまう。
上記のリンクを踏んだ後に、コミットハッシュが表示されているプルダウンメニューを押し、適当な名前でブランチを切ると再び参照できるようになる。
コミット履歴を完全に削除するためには、前述の「履歴情報を削除する」に記載したように、新たにGitHubリポジトリを作成するか、GitHubのサポートに連絡してキャッシュを消してもらう必要がある。