間違ってremoteにpushしたファイルを削除したい時

誤ってパスワードなどの秘密情報が含まれたファイルをremoteにpushしてしまった時。
普通にgit rm hogeしただけだと当然ながら履歴が残ってしまうので、履歴ごと改変したい時のやり方です。
リモートの履歴を改変することになるので、チーム開発の際は混乱が起きない様ご注意ください。

前提条件

こんな履歴があったとします。

$ git log --oneline
fae133a (HEAD -> master, origin/master) 3rd commit.
3ee314f 2nd commit.
a3af1e4 Initial commit.

よく見ると、パスワードが書かれたsecret.fileをcommit(&push)しています!

$ git log -p -2
commit fae133a633e21e7feb94c3994c276ef86d41210c (HEAD -> master, origin/master)
Author: makicamel
Date:   Tue Mar 19 19:00:30 2019 +0900
    3rd commit.
# (略)

commit 3ee314fc2f06bb7118229dc25ece3b54af889fb4
Author: makicamel
Date:   Tue Mar 19 19:00:00 2019 +0900

    2nd commit.

diff --git a/secret.file b/secret.file
index e69de29..9c3f6c8 100644
--- a/secret.file
+++ b/secret.file
@@ -0,0 +1 @@
+PASSWORD # <= これを消したい!

git rm secret.fileをするとファイルは消せますが、履歴は消せません。
履歴自体を消したいので、commitからやり直します。

commitを取り消し

まずはローカルで変更を修正。
git logで戻りたい履歴のコミットのハッシュ値を確認、そこまで戻ります。
git resetオプションはこちらに詳しいですが--hard--mixed--softとあります。

$ git log --oneline
fae133a (HEAD -> master, origin/master) 3rd commit.
3ee314f 2nd commit.     # <= ここでsecret.fileを追加した
a3af1e4 Initial commit. # <= ここに戻れればOK

今回はファイルの変更はそのまま、コミットだけ取り消したいので--softします。

$ git reset a3af --soft
$ git log --oneline
a3af1e4 (HEAD -> master) Initial commit.

ファイルをgit管理対象から外す

.gitignoreに外したいファイルを追記。

$ echo "secret.file" > .gitignore

ただしこのままpushしても、gitが管理してくれているままになるので、git rmします。
git rmだとファイルごと削除されるので、ファイルを残すよう--cachedオプションをつけて実行。

$ git rm --cached secret.file

remoteにpush

あとはremoteにpushするだけ!
リモートとローカルで不整合が起きるので、-fオプションでpushします。

$ git push -f

無事履歴からファイルを削除することができました!