
本来、誤ってAPIのトークンやパスワードをハードコーディングした状態でGitHubリモートリポジトリにプッシュしてしまった場合、トークンやパスワードそのものを変更するのがセオリーであることが前提です。
その上で、関係ないけどふざけた情報を環境構築時にパスワードにしていたからなんか気持ち悪い!履歴から消したい!って場合がある。
PASSWORD=45451919
とかね。
例えば自分のニックネーム的なパスワードを使って仮で環境構築してた時のデータをpushしちゃったりとか。
リモートリポジトリ上からファイルを履歴含めて丸ごと葬り去って、なかったことにできる方法もあるにはある。
責任は取れないので、必ずバックアップをとってから行ってね。
前置きが長くなるので、あえて注意事項は最後にまとめます。
ジャンプできる目次
リポジトリをクローンしてそのディレクトリに移動。
手元にプロジェクトのディレクトリがなかったらcloneしてね。あったらそのディレクトリに移動してね。
git clone your-repo-url hoge
cd hoge
作業をスタッシュ(必要ならば)
未コミットの変更がある場合、スタッシュします。とりあえずやっとこ。
git stash
git stash
コマンドは、ワーキングディレクトリにある未コミットの変更(ステージングエリアとワーキングツリーの両方)を一時的に保存して、ワーキングディレクトリをクリーン(最後のコミットの状態)にするためのものです。つまり、まだコミットしていない変更を一時的に退避させるのです。
これは、次のようなシナリオで非常に便利です:
- 現在のブランチで作業中だが、別のタスク(例えば、バグ修正など)のために一時的に別のブランチに切り替える必要がある場合
- 破壊的な変更(例えば、リファクタリングやライブラリのアップデートなど)を安全にテストするために、一時的に変更を退避させてワーキングディレクトリをクリーンにしたい場合
- ヒストリーを書き換えるようなコマンド(
rebase
やfilter-branch
など)を安全に実行するために、未コミットの変更を一時的に退避させたい場合
具体的な使用例として、未コミットの変更を持っている状態で別のブランチにチェックアウトしようとすると、Gitはそれを防ぎます。なぜなら、チェックアウトすることでワーキングディレクトリのファイルが上書きされ、未コミットの変更が失われる可能性があるからです。この未コミットの変更をstash
することで、安全に別のブランチに移動することができ、後でstash
した変更を取り出して作業を再開することができます。
filter-branch
でヒストリーからファイルを削除
開発環境(手元にあるローカルのPC)からもデータが消えるので注意。
どっか関係ない場所にコピーしておこう。
指定されたファイルのヒストリーを削除します。
今回は、.env
と.env.example
を履歴ごと葬り去りたいとする。
git filter-branch --force --index-filter \\
"git rm --cached --ignore-unmatch .env .env.example" \\
--prune-empty --tag-name-filter cat -- --all
もちろんリポジトリ直下以外のフォルダも消せるので、/hoge/.env
みたいに指定してもOK
もし
Ref 'refs/heads/main' was rewritten zsh: no such file or directory: git rm --cached --ignore-unmatch
のようなエラーが出る場合は、\
を1つずつ減らしたコマンドを試そう。
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch r.env .env.example" \
--prune-empty --tag-name-filter cat -- --all
バックアップとガベージコレクションをクリーンアップ
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
変更をリモートリポジトリにプッシュ
git push origin --force --all
git push origin --force --tags
これでGitHubなどのリモートリポジトリからも初めからファイルがなかったかのように履歴ごと消える。
注意事項
- そもそも非推奨のやりかたである
- 元データも消える
- 結構危険
- チームで作業した場合不整合が発生するかも
- チームで作業している場合、それぞれの開発者の端末に作業完了後にgit cloneしなおしたほうがいいかも