git filter-repoを使って過去のコミットの内容を書き換える

git-filter-repoを使ってgitの履歴の書き換えを行った。

目的

うっかりローカルのパスの文字列をハードコードしたままpushしてしまったため、これをなかったことにしたいと思った。

少し具体的に述べると、/ukkari/path/some/path/to/fooのように書き換えようと思った。

個人のリモートレポジトリにpushまでしていたので、これを修正することを最終目的としたい。

調査

書き換えツールについて、適当に調べると、git filter-branchというものがあるそうだが、これは公式のツールであるにも関わらず、非推奨(ドキュメントページ)になっており、代わりに、git filter-repoを使ってほしいと書いてある。

どうやら公式のツールは効率的でないらしい。推奨された通り、git filter-repoを使うことにする。

用意

git filter-repoは1つのPythonファイルで提供されており、自分で/usr/local/binフォルダなどに配置してかまわないらしい。普通にPythonモジュールとしてインストールもできるし、パッケージマネージャでも提供されているようだ。

上記にもあるが下記のgithubレポジトリを参照:

GitHub - newren/git-filter-repo: Quickly rewrite git repository history (filter-branch replacement)
Quickly rewrite git repository history (filter-branch replacement) - newren/git-filter-repo

使ったコマンド

--dry-runを付けてテストするといい。ドキュメント通り、cloneしたてのものを使えば安心。

ちょっと迷走したが、最終的に履歴を書き換えるためのコマンドは以下:

# ==>の左側の内容にマッチする部分を==>の右側に書き換える。
git-filter-repo --replace-text <(echo '/ukkari/path==>/some/path/to/foo')

書き変わるのはスナップショットの部分で、--pathでファイル名を指定すると、そのファイル以外は消えてしまうようだった。--invert-pathsを付けると、反転できるようだが、今度は指定したファイルが消えてしまうと思う。(未実施)

remoteを再指定してpush

git filter-repoで履歴の書き換えを行った時点でremoteoriginなどは消去(移動?)される。そのため、リモートレポジトリにプッシュするときは再びgit remote add origin URLする必要がある。

そして、ハッシュが合わないので、git push -u -f origin mainでプッシュする必要がある。

ここまで行えば最終目的は達成できる。

他に使いそうなコマンド

# 特定のファイルをすべての履歴から削除
git-filter-repo --path filepath_to_be_deleted --invert-paths

--invert-pathsを付けないでおくと、--pathで指定したファイルだけ残してすべて消えるので注意。 フィルターして反転するイメージを持っていれば間違いにくいと思う。

globや正規表現も使えるようだ。やはり--invert-pathsには気をつけたい。

参考

参考:

git でリポジトリを整理して容量削減するときに嵌った話
タイトル通りです。丸一日消滅したので同じことが起きないように書き残しておきます。 要約: filter-branch を使うのはやめよう。filter-repo を使おう。 背景 個人の進捗管理用に使用しているリポジトリの容量が肥大化してき...
git-filter-repo - Qiita
ある日、まずいファイルをコミットしちゃったなーと気が付き歴史改変を試みた。「git 履歴 削除」などで検索すると git filter-branch を使うらしい。そこでこのコマンドのドキュメント …
タイトルとURLをコピーしました