問題:大きなファイルサイズによるGit Pushの拒否
最新の変更をGitHubにプッシュしようとしています。おそらく夜遅く、突然Gitがプッシュを拒否しました。次のようなメッセージが表示されます。
remote: error: File path/to/file.bin is 150.00 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.
to github.com/your-org/your-repo.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'github.com/your-org/your-repo.git'
このメッセージは、何が問題なのかを正確に示しています。リポジトリにGitHubの個別のファイルサイズ制限(100MB)を超えるファイルがあるということです。
なぜこれが起こるのか
GitHubには、Gitリポジトリ内の個々のファイルに対して100MBという厳格な制限があります。リポジトリ全体のサイズは5GB(有料プランではそれ以上)まで可能ですが、単一のファイルが100MBを超えることはできません。これは、現在作業ディレクトリにあるファイルだけでなく、リポジトリの履歴に一度でもコミットされたすべてのファイルに関係します。
Gitは、すべてのファイルのすべてのバージョンを追跡します。大きなファイル(動画、大きなアーカイブ、データベースダンプ、コンパイル済みバイナリなど)をコミットした場合、後でgit rmで削除しても、その存在はリポジトリの履歴に残ります。プッシュすると、GitHubのpre-receiveフックは、受信するコミットの履歴全体をスキャンします。その履歴のどこかに100MBを超えるブロブ(ファイルのコンテンツ)が見つかった場合、プッシュを拒否します。
分析:原因の特定
エラーメッセージは通常、問題のファイル(例:path/to/file.bin)を直接指し示します。他の大きなファイルを見つけたり、さらに調査したりする必要がある場合は、git rev-listやgit ls-treeのようなツールを使用できますが、特に修正の準備をする際には、git filter-repoのようなツールに履歴を分析させるのが最も簡単な方法です。
即時の修正:git filter-repoによる履歴の書き換え
これを修正するには、リポジトリの履歴から大きなファイルを削除する必要があります。これは履歴を書き換えることを意味し、強力な操作です。特に共有リポジトリで作業している場合は、その影響を理解することが重要です。
警告:履歴の書き換えは破壊的です。 コミットのSHAが変更されます。他の人があなたのリポジトリをクローンしている場合、彼らは新しい履歴と同期するために、再クローンするか、特定のGitコマンドを実行する必要があります。このことを理解しているか、新しいクローンまたは個人のブランチで作業している場合にのみ続行してください。
ステップ1:git filter-repoのインストール
git filter-repoは、Git履歴を書き換えるための推奨ツールであり、古く、遅く、より複雑なgit filter-branchに代わるものです。これはPythonスクリプトです。
macOS (Homebrewを使用):
brew install git-filter-repo
Linux (pipを使用):
pip3 install git-filter-repo
または、必要であればソースからインストールしてください:https://github.com/newren/git-filter-repo
ステップ2:新しいクローンの作成(重要な安全対策)
履歴をいじる前に、常に新しいクローンで作業してください。そうすれば、何か問題が発生しても、主要な作業コピーを破損させることはありません。
cd ..
git clone git@github.com:your-org/your-repo.git your-repo-cleaned
cd your-repo-cleaned
ステップ3:git filter-repoを実行して大きなブロブを削除する
このコマンドは、リポジトリの履歴を書き換え、100MBを超えるすべてのファイルを削除します。それらのファイルが存在したすべてのコミットから削除するのに十分スマートです。
git filter-repo --strip-blobs-bigger-than 100M
git filter-repoが実行され、その進捗状況が表示されます。大きなリポジトリでは時間がかかる場合があります。完了すると、ローカルリポジトリの履歴は書き換えられ、大きなファイルは削除されます。
ステップ4:GitHubへの強制プッシュ
履歴を書き換えたため、ローカル履歴がリモートと分岐しているため、通常のgit pushは拒否されます。強制プッシュする必要があります。
特に共有リポジトリでは、他の誰かがその間にプッシュした場合にリモートの変更を上書きするのを防ぐため、安全のために--force-with-leaseを使用してください。
git push --force-with-lease origin
``をプッシュするブランチ名(例:mainまたはmaster)に置き換えてください。
ステップ5:チームへの通知(共有リポジトリでは必須)
これが共有リポジトリである場合、すぐにチームに通知する必要があります。他の全員は、新しい履歴と同期するために、自分の作業をリベースするか、リポジトリを再クローンする必要があります。彼らにとって最も簡単な方法は、多くの場合、ローカルコピーを削除して再クローンすることです。
将来の問題を防止する:Git LFSによる大きなファイルの管理
履歴をクリーンアップした後も、大きなファイルを適切に処理するための戦略が必要です。ここでGit Large File Storage (Git LFS)が登場します。
Git LFSは、Gitリポジトリ内の大きなファイルを小さなテキストポインタに置き換えます。実際のファイルコンテンツは、リモートのLFSサーバー(GitHubのLFSサーバーなど)に保存されます。ブランチをクローンまたはチェックアウトすると、Git LFSが実際の大きなファイルをダウンロードします。これにより、Gitリポジトリが軽量に保たれ、100MBの制限を回避できます。
ステップ1:Git LFSのインストール
まず、Git LFSがシステムにインストールされていることを確認してください。
macOS (Homebrewを使用):
brew install git-lfs
Linux (Debian/Ubuntu):
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
sudo apt-get install git-lfs
Windowsでは、git-lfs.github.comからインストーラーをダウンロードするか、Chocolateyを使用できます。
choco install git-lfs
ステップ2:リポジトリのLFS設定
リポジトリ(元のクリーンなリポジトリ、またはyour-repo-cleanedで作業を続けたい場合はそちら)に移動し、Git LFSを初期化します。
git lfs install
このコマンドは、ローカルリポジトリにGit LFSフックを設定します。
ステップ3:ファイルタイプの追跡
Git LFSにどの種類のファイルを追跡するかを指示します。一般的な大きなファイル拡張子にはワイルドカードを使用します。これにより、.gitattributesファイルにエントリが追加されます。
git lfs track "*.bin"
git lfs track "*.zip"
git lfs track "*.mp4"
git lfs track "*.psd"
追跡後、.gitattributesファイルをコミットする必要があります。
git add .gitattributes
git commit -m "Configure Git LFS to track large files"
ステップ4:通常通り大きなファイルを追加してコミットする
これで、追跡されたパターンに一致する新しいファイル(またはまだコミットされていない既存のファイル)は、LFSによって処理されます。それらを追加し、通常通りコミットします。
git add path/to/another_large_file.bin
git commit -m "Add another large binary file via LFS"
git push origin
プッシュ中にGit LFSの出力が表示され、大きなファイルがLFSサーバーにアップロードされていることが示されるはずです。
検証ステップ
修正を実行し、LFSを設定した後:
- プッシュの成功を確認:
git pushコマンドは、リモート拒否エラーなしで完了するはずです。 - GitHubリポジトリのサイズを確認: GitHubのリポジトリ設定に移動します。報告されるサイズが更新されるまでに少し時間がかかる場合がありますが、最終的には履歴から大きなファイルが削除されたことが反映されるはずです。
- LFS追跡の検証: Git LFSを設定した場合、追跡されるべきファイルを確認します。ローカルリポジトリで、LFS追跡されている大きなファイルを開くと、実際のファイルコンテンツの代わりに小さなテキストポインタが表示されるはずです。実際のコンテンツは、Git LFSがアクティブなときにダウンロードされます。
これらの手順により、リポジトリはクリーンになり、プッシュはブロック解除され、今後大きなファイルを管理するための確実な戦略が手に入ります。

