• SIS Lab
  • >
  • Blog
  • >
  • git-filter-repoを利用してGitリポジトリを最適化する

git-filter-repoを利用してGitリポジトリを最適化する

更新日:2023.07.24 作成日:2023.07.24

背景

普段ブログのコンテンツ管理に利用しているwww.meganii.comのリポジトリの容量(.git/objects)がなぜか数GBになっている。普段、ビルドするときはシャロークローンを使うため気にならないが、すべての履歴を取得する場合、数分から数十分要する。ほぼテキストのため、不要な履歴を削って軽量化・最適化したい。

結論

  • git filter branchではなく、git公式サイトでも推奨されている git-filter-repo を利用すべき。
  • git-filter-repoのanaliyze結果から、過去に/publicやリポジトリ直下に配置してしまっていた生成物(HTML)がかさ増しの原因であった。
  • これを機会に、hugoのthemeフォルダも別リポジトリに分離し、過去履歴に残っていたメールアドレスも最新のものに置き換えた。
  • 不要な履歴を削除し整理した結果、リポジトリの容量(.git/objects)が1.9GBから14MBに減少した。

作業メモ/ポイント

git filter-branchではなくサードパーティのgit-filter-repoを利用する

「Please use an alternative history filtering tool such as git filter-repo.」と git公式ドキュメント(2.41.0) にも、 git-filter-repo のような代替ツールを利用するように記載がある。 git でリポジトリを整理して容量削減するときに嵌った話 | おいもログ も参照した上で、素直に git-filter-repo を利用した。

WARNING git filter-branch has a plethora of pitfalls that can produce non-obvious manglings of the intended history rewrite (and can leave you with little time to investigate such problems since it has such abysmal performance). These safety and performance issues cannot be backward compatibly fixed and as such, its use is not recommended. Please use an alternative history filtering tool such as git filter-repo. If you still need to use git filter-branch, please carefully read SAFETY (and PERFORMANCE) to learn about the land mines of filter-branch, and then vigilantly avoid as many of the hazards listed there as reasonably possible.
Git - git-filter-branch Documentation

git filter-branch has many pitfalls, and is no longer the recommended way to rewrite history. Instead, consider using git-filter-repo, which is a Python script that does a better job for most applications where you would normally turn to filter-branch. Its documentation and source code can be found at  https://github.com/newren/git-filter-repo .
Git - Rewriting History

インストールは How do I install it? を参照し、 git-filter-repo script のPythonスクリプトをプロジェクトに配置した。

analyzeの結果をもとに何がリポジトリを肥大化させているのかあたりを付ける

まず、新しく作業用のリポジトリをcloneし、.git/objectsの容量を次のコマンドで確認した。1.9GBもある。

 du -hs .git/objects
 1.9G    .git/objects

次のコマンドを実行し、.git/filter-repo/analysisに解析結果を出力する。

python3 git-filter-repo --analyze

path-all-sizes.txtには、だいたいサイズが大きいものから順にファイルが並んでいる。たとえば、下図は初回の実行結果だが、htmlファイルが並んでいることが見て取れる。おそらく、過去リポジトリ直下にHTMLを展開し、コミットしてしまったゴミと思われる。

git filter-repo –analyzeの実行結果
次のコマンドを実行し、コミット履歴から--pathで指定するディレクトリを削除する。

python3 git-filter-repo --path public/ --path tags/ --path en/ --path blog/ --path category/ --path tags/ --path tmp --invert-paths --force

ちなみに、git-filter-repo --pathは指定したファイルもしくはディレクトリを残し、それ以外はフィルタするというのがデフォルトの動きである。そのため、特定のファイルもしくはディレクトリを削除する場合は、--invert-pathsのオプションを付加する。

また、該当プロジェクトに差分がある場合は、--forceオプションを付加しないと実行できない。

上記コマンドで生成物の削除だけで1.9GB→47MBに減った。どれだけ不要なファイルを蓄えていたのかがわかる。

du -hs .git/objects
47M     .git/objects

同じ要領で、python3 git-filter-repo --analyzeを実行しながら、その他削除可能なファイルおよびディレクトリがないかを確認する。既に.git/filter-repo/analysisが存在する場合は、エラーになるため、適宜.git/filter-repo/analysis1などリネームする必要がある。

その後、analyze結果を見ながら、削除を繰り返し、最終的に14MBと妥当な大きさに収まった。

du -hs .git/objects
14M     .git/objects

Authorのメールアドレスを変更する

次のような新旧メールアドレスのマッピングファイル(mailmap)を用意する。

次のコマンドを実行し、過去の履歴のAuthorのメールアドレスを変更する。

python3 git-filter-repo -f --mailmap mailmap

remote originの情報は削除される

git-filter-repoのコマンドを実行すると、remote originの情報は削除される。これは履歴書き換えによる影響を避けるため、新しいリポジトリにpushすべきという作者の意図によるもの。

4.Push your new repository to its new home (note that refs/remotes/origin/* will have been moved to refs/heads/* as the first part of filter-repo, so you can just deal with normal branches instead of remote tracking branches).
DISCUSSION | git-filter-repo(1)

今回も、新しいリポジトリにpushすべく、既存のwww.meganii.comwww.meganii.com.oldにリネームした上で、privateリポジトリに変更した。そして、空いたwww.meganii.comに対して、pushした。

今後の課題とまとめ

いままでgitの履歴を改編したことがなかったのでよい勉強になった。今回は、自分ひとりのプロジェクトであったため、git push --forceしたときの影響は気にしなかった。

しかし、チームで開発しているリポジトリに同じような改編を加える場合の影響は意識する必要がある。今後実施する際の課題とする。

参考URL

Related contents