ブランチの履歴から特定のファイル(と非表示ファイル)以外を削除する

パスワードなど、特定のファイルを履歴から削除するというのはのはすぐ見つかったが、特定のファイル以外を削除するというのだと見つからなかったのでここに書いておく。

目的

リポジトリ内の特定のディレクトリ(もしくはファイル)を他のリポジトリと共有したい。 そのためにそのディレクトリ(もしくはファイル)のみが含まれるブランチを作りたい。

特定のディレクトリをルートにして別のリポジトリにするならそれ用の git subtree split や git filter-branch --subdirectory-filter があるのだが、今回は切り出したあともcherry-pickで切り出し元の更新を持ってきたかったので、階層はそのままにしたかった。

結論

切り出し先のブランチを作成、チェックアウトしてから以下を実行する。
※念の為作業用にクローンしてから実行することを推奨

git filter-branch --tree-filter 'ls |  grep -v -E "target_dir_or_file" | xargs -r git rm  -rf  --ignore-unmatch' --prune-empty HEAD

これで今のブランチ(履歴含む)からtarget_dir_or_file(と.gitignoreを始めとした非表示ファイル)以外のファイルが削除される。切り出し元含む他のブランチはそのままなので、多くの場合既存のブランチとはunrelatedな状態になるはず。

前述の通り非表示ファイルが残っているが、今回は.gitignoreくらいしかなかったので気にしないことにした。

参考ページ