[実話] GitHubの「ファイルサイズ制限」エラーとの長い戦い ~BFGでも解決できない履歴をfilter-branchで切り捨てる~

GitHubのファイルサイズ制限エラーとの戦いを記録する:BFGが失敗したとき、filter-branchが履歴を切り裂く
2025年8月10日
こんにちは!Webアプリケーションを開発していると、予期せぬGitエラーに遭遇することがあります。今回は、GitHubのファイルサイズ制限エラーとの格闘を記録したブログ記事をまとめました。
始まり:GitHubのファイルサイズ制限を超える悪夢
ある日、Next.jsプロジェクトに変更をプッシュしようとしたところ、見慣れないエラーメッセージが表示されました。
remote: error: File <プロジェクト名>/node_modules/... is 129.50 MB; this exceeds GitHub's file size limit of 100.00 MB remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com. ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://github.com/<ユーザー名>/<リポジトリ名>'
原因は単純明快でした。Next.jsプロジェクトディレクトリに.gitignoreファイルを追加し忘れており、巨大なnode_modulesフォルダ全体をコミットしてしまっていたのです。
「なんだ、簡単じゃないか!」と思い、すぐに.gitignoreファイルを追加し、キャッシュをクリアする標準コマンドを実行しました。
.gitignoreに/node_modulesを追加
キャッシュを削除して再コミット
git rm -r --cached . git add . git commit -m "fix: add .gitignore"
しかし、再度プッシュしても同じエラーが発生しました。「大きなファイルコミット」がGitの履歴に記録されると、そう簡単には消えません。
ラウンド2:推奨ツール「BFG」が機能しない…?
履歴の改訂という旅に出ることを決意し、Gitが公式に推奨するBFG Repo-Cleanerという専用ツールを使用することにしました。
- Javaを準備し、BFGをダウンロードします。
- 安全のためにミラークローンを作成します。 git clone --mirror https://github.com/<ユーザー名>/<リポジトリ名>.git
- BFGを実行します!
しかし、ここからが本当の戦いの始まりです。
試行1:フォルダ名で削除 → 失敗!
$ java -jar ../bfg-x.x.x.jar --delete-folders node_modules
BFG aborting: No refs to update - no dirty commits found??
試行2:最新のコミットを保護しない → 失敗!
$ java -jar ../bfg-x.x.x.jar --delete-folders node_modules --no-blob-protection
BFG aborting: No refs to update - no dirty commits found??
試行3:ファイルサイズで削除 → 失敗!
$ java -jar ../bfg-x.x.x.jar --strip-blobs-bigger-than 100M
Warning: No large blobs matching criteria found in packfiles
試行4:git gcでデータベースを最適化して再試行 → 失敗!
$ git gc $ java -jar ../bfg-x.x.x.jar --strip-blobs-bigger-than 100M
Warning: No large blobs matching criteria found in packfiles
試行5:ファイル名を直接指定 → 失敗!
$ java -jar ../bfg-x.x.x.jar -D <大きなファイル名>
BFG aborting: No refs to update - no dirty commits found??
何を試しても、BFGは大きなファイルを見つけることができず、プロセスを中断しました。おそらくサブディレクトリにあったためか、リポジトリが特殊な状態だったためか…理由は不明ですが、BFGの使用を諦めるしかありませんでした。
最終決戦:禁断のGit filter-branch
残された選択肢は一つだけでした。Gitに組み込まれた究極の武器、git filter-branchです。このコマンドは非常に強力ですが、リポジトリを破壊するリスクも伴います。
[最も重要] 実行する前に、必ずプロジェクトフォルダ全体をバックアップしてください!
最悪の事態に備え、以下のコマンドを実行しました。
- 履歴の書き換え
これはリポジトリの全履歴をスキャンし、指定されたフォルダ(この場合は<プロジェクト名>/node_modules)を削除します。リポジトリのサイズによっては、完了までにかなりの時間がかかる場合があります。
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch <project_name>/node_modules' --prune-empty --tag-name-filter cat -- --all
- リポジトリのクリーンアップ
filter-branchによって残されたバックアップデータを完全に削除し、リポジトリを最適化します。
バックアップ参照を削除(Windows PowerShellでエラーが発生したため、フォルダを直接削除)
PowerShellの場合:
Remove-Item -Recurse -Force .git\refs\original
Linux/macOS/Git Bashの場合:
rm -rf .git/refs/original/
参照ログと不要なデータを削除
git reflog expire --expire=now --all git gc --prune=now
- 強制プッシュ
ローカルのリビジョン履歴が正しいと仮定して、GitHubに強制プッシュします。
git push origin --force --all git push origin --force --tags
このプッシュが成功したとき、長い戦いの終わりを告げるプログレスバーが表示されました。
まとめ
- 最初から.gitignoreにnode_modulesを含めること!(基本だが最も重要)
- 大きなファイルをGitの履歴にコミットしてしまった場合は、履歴を書き換える必要があります。
- 履歴を書き換えるには、まずBFG Repo-Cleanerを試すのが安全で簡単です。
- BFGが機能しない稀なケースでは、git filter-branchが最後の手段です。
- filter-branchやpush --forceのような危険な操作を実行する前に、必ず変更をバックアップしてください!
この記事が、同じエラーで苦しんでいる誰かの助けになることを願っています。