はじめに
事の始まりは,Git LFSの容量制限に引っかかり,特定のオブジェクトを削除する必要が出てきたこと.
厄介なことに直前のcommitだけでなく,既にpushをはじめとした諸々の操作をした履歴全てから,当該ファイルを削除する必要があります.とはいえ,入り組んだ履歴から手動で削除するのは大変すぎる……
そんな時に使えるのがgit filter-repo
で,サードパーティ製ながら公式でも推奨1されているOSSライブラリがあります.
事件の経緯
git filter-repo
を用いて,Git LFSのuninstallの後処理をしていました.
ChatGPTやGithub Copilotに訊きながら進めていたところ,以下のようなコマンドを実行するように求められました.
~$ git filter-repo --path-glob '*.zip' --invert-paths
流石に,初めて見るコマンドだったので,安易に実行することはせずにブログなどを調べてみて,その動作内容を調べてから実行しました.
ところが,意図していた動作とは異なる動作であることに気づいた時には後の祭り.当該ファイルは全て削除されてしまっていました.
求めていた動作は,ローカルからはファイルを削除せずに,git / Githubの履歴からのみ削除するというものでした.
resetも試しましたが,どうにもならず……
どうすればよかったのか
git filter-repo
の取り扱いは,便利な分だけ気をつけなければならないことに身をもって気付かされたところで,本記事の本題である,どうするべきであったかを復習していきたいと思います.
バックアップを作成してから作業をおこなう
どんな操作についても言えることですが,特に破壊的な処理をおこなう際にはバックアップを作成しておくことが最適です.
幸いにも,今回削除してしまったファイルは別にオリジナルがあるデータだったため,手間はかかったものの,復元することができました.
オリジナルが別にある復元可能なデータであったこと,作業し始めたばかりの新しめのリポジトリであったことから,大雑把な処理をしてしまいましたが,これが重要なデータであったと思うとゾッとします.
新しいリポジトリを作成して作業をおこなう
破壊的な処理をおこなったリポジトリをpushなどで上書きすることは望ましくないようです.23
可能な限りgit filter-repo
を実行する前に,それまでの変更をpushした状態で作業をするべきとのことです.
また,git filter-repo
はデフォルトでremoteの情報が削除されるようになっているようです.
そうした仕様も上書きを防止するというところから来ているようです.
--dry-run
を用いる
実行予定の操作が意図したものと異なっていないかを確認するためのオプションとして,--dry-run
というものがあるようです.4
これを用いることで,私のような悲しい事故を減らすことができるかもしれません.
最後に
今回は,git filter-repo
を用いた結果,発生してしまった悲しい事故について,その再発防止のための復習をおこないました.
上記に挙げたものが全てではないと思いますが,パッと調査した限りではこのような感じでした.
gitは多くの場面で決まった操作しかしない一方で,それ以外の操作となるとまだまだ知識不足であると痛感しています.