Git管理していたファイルを履歴から完全に削除する方法を整理する
Git管理していたファイルを現在の管理対象から外すだけでなく、過去のコミット履歴からも削除する方法を整理する
今日やったこと
- Gitで一度管理していたファイルを、履歴から完全に削除する方法を整理した
.gitignoreに追加するだけでは、過去にコミット済みのファイルは消えないことを確認した- 現在の管理対象から外す操作と、過去の履歴から削除する操作の違いを確認した
- 履歴を書き換える場合は、
git filter-repoなどの専用ツールを使うことを確認した - 履歴を書き換えたあとは、リモートリポジトリへ
--force付きで push する必要があることを確認した
学んだこと
Gitで管理していたファイルを削除するときは、目的によって操作が変わる。
現在のコミットからファイルを消したいだけであれば、通常の git rm を使えばよい。
git rm path/to/file
git commit -m "Remove file"
ただし、この方法では過去のコミット履歴にはファイルが残る。
たとえば、誤ってパスワード、APIキー、秘密鍵、大きすぎるバイナリファイルなどをコミットしてしまった場合は、現在のコミットから削除するだけでは不十分になる。
その場合は、履歴そのものを書き換えて、過去のコミットからも対象ファイルを削除する必要がある。
代表的には、git filter-repo を使う。
git filter-repo --path path/to/file --invert-paths
このコマンドは、指定したファイルを履歴全体から取り除くためのもの。
--path path/to/file- 履歴から削除したいファイルを指定する
--invert-paths- 指定したパス以外を残す、つまり指定したファイルを削除する
ディレクトリごと履歴から削除したい場合は、ディレクトリを指定する。
git filter-repo --path path/to/directory/ --invert-paths
履歴を書き換えたあとは、コミットIDが変わる。
そのため、リモートリポジトリに反映する場合は通常の git push ではなく、force push が必要になる。
git push origin main --force
タグも含めて履歴を書き換えた場合は、タグも force push する必要がある。
git push origin --tags --force
ただし、履歴の書き換えは影響が大きい操作なので、共有リポジトリで実行する場合は注意が必要。
すでに他の人が clone や pull している場合、その人のローカルリポジトリと履歴が食い違う。
そのため、実行前にチームへ共有し、必要であれば再 clone してもらう方が安全。
また、秘密情報を削除した場合でも、すでに外部に漏れている可能性は残る。
そのため、APIキーやパスワードを誤ってコミットした場合は、履歴から削除するだけでなく、キーの無効化や再発行も必要になる。
あいまいなこと
git filter-repoとgit filter-branchの違い- 履歴を書き換えたあと、他の作業者のローカルリポジトリをどう復旧するのがよいか
次にやること
git filter-repoのインストール方法を確認する- 履歴を書き換えたあとのチーム作業者向け手順を整理する
- 誤って秘密情報をコミットしないための
.gitignoreや pre-commit の使い方を整理する