🚮

GithubとGitの履歴から特定のファイルを完全に削除する

2024/01/26に公開

はじめに

「gitの履歴を完全に削除する」をしたのでメモする。
下記記事にお世話になった。
https://gist.github.com/ktx2207/3167fa69531bdd6b44f1

シチュエーション例

secret/key.keystoreがバージョン管理に含まれていることを開発しているときに気付いた。
しかも、initial commitに入っていた。
しかもGithubのpublicリポジトリにある。
別に単体で何かされることはないが、気持ち悪いので消したい。
gitの歴史から抹消したい。

方針

Githubに上げてしまったのは、ローカルで歴史を抹消してpushしても残るかもしれないという話を聞いた。(実際のところを知っている人がいたら教えて欲しい)
そこで、下記手順で抹消を行う。

  1. ローカルを最新にする(チェックアウト or update)
  2. ローカルで歴史を削除
  3. Githubのリポジトリを削除(別名にするでもOK)
  4. Githubのリポジトリを新規作成
  5. 歴史削除済みのローカルを新規Githubリポジトリにpush
  6. それをクローンする

操作手順

ローカル環境の準備

すでにチェックアウト済みなら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だったとする

  1. Githubでリポジトリのrenameをする(hoge -> hoge-old)
  2. Githubで新規リポジトリを作成する(hoge)

1.で、リポジトリを削除しても良いが、万が一何かあったときに戻せないので、全部完了してからrenameしたものを消すのが良いと思う。

リポジトリへpush

リモートが正しいことを確認する

git remote -v

pushする

git push --force origin main

Githubで確認

対象のリポジトリで、リポジトリ内検索などで消したいファイルがないことが確認できる。

クローン

新しく生まれ変わったリポジトリをクローンする。
そこでgit logを見ると、履歴が完全に消えていることが確認できる。

最後に

git gcの後にgit logをした時に履歴に消したいファイルがが表示されたが、それをpushしたものを新規でクローンしたら履歴は表示されなかった。
何かまだ消せていないキャッシュがあるのかもしれないが、クローンしたらうまく消えていたので良しとする。
こんな手段が用意されているとは、git様々である。

Discussion