GithubとGitの履歴から特定のファイルを完全に削除する
はじめに
「gitの履歴を完全に削除する」をしたのでメモする。
下記記事にお世話になった。
シチュエーション例
secret/key.keystoreがバージョン管理に含まれていることを開発しているときに気付いた。
しかも、initial commitに入っていた。
しかもGithubのpublicリポジトリにある。
別に単体で何かされることはないが、気持ち悪いので消したい。
gitの歴史から抹消したい。
方針
Githubに上げてしまったのは、ローカルで歴史を抹消してpushしても残るかもしれないという話を聞いた。(実際のところを知っている人がいたら教えて欲しい)
そこで、下記手順で抹消を行う。
- ローカルを最新にする(チェックアウト or update)
- ローカルで歴史を削除
- Githubのリポジトリを削除(別名にするでもOK)
- Githubのリポジトリを新規作成
- 歴史削除済みのローカルを新規Githubリポジトリにpush
- それをクローンする
操作手順
ローカル環境の準備
すでにチェックアウト済みならOK。
最新の状態にすること。
なければリモートからcloneする。(一例)
git clone https://ユーザー名:token@github.com/ユーザー名/リポジトリ.git フォルダ名
消すファイルの存在を確認する
git log --all --name-status --pretty=short --graph -- secret/key.keystore
消す
git filter-branch --tree-filter 'rm -f secret/key.keystore' HEAD
警告が出た後、数秒で削除が実行される。
少しだけ猶予があるので、間違えた場合はCtrl-CをすればOKっぽい。
終わったら、現在の状態で、指定したファイルが消えていることが分かる。
git logを見ると、ログ自体はまだある。
他のブランチからも消す
git filter-branch --tree-filter 'rm -f secret/key.keystore' HEAD --all
reflogを削除
git reflog expire --expire=now --all
git gcを実行
git gc --aggressive --prune=now
ここでgit logを確認しても、消す対象のファイルのコミットはまだある。
Githubのリポジトリの作り直し
リポジトリの名前がhogeだったとする
- Githubでリポジトリのrenameをする(hoge -> hoge-old)
- Githubで新規リポジトリを作成する(hoge)
1.で、リポジトリを削除しても良いが、万が一何かあったときに戻せないので、全部完了してからrenameしたものを消すのが良いと思う。
リポジトリへpush
リモートが正しいことを確認する
git remote -v
pushする
git push --force origin main
Githubで確認
対象のリポジトリで、リポジトリ内検索などで消したいファイルがないことが確認できる。
クローン
新しく生まれ変わったリポジトリをクローンする。
そこでgit logを見ると、履歴が完全に消えていることが確認できる。
最後に
git gcの後にgit logをした時に履歴に消したいファイルがが表示されたが、それをpushしたものを新規でクローンしたら履歴は表示されなかった。
何かまだ消せていないキャッシュがあるのかもしれないが、クローンしたらうまく消えていたので良しとする。
こんな手段が用意されているとは、git様々である。
Discussion