Git Clone/Pushの失敗を修正する: error: RPC failed; curl 18 transfer closed with outstanding read data remaining

intermediate📦 Git2026-05-03| Linux、macOS、Windows上のGit 2.x — HTTP/HTTPS経由の大規模リポジトリで主に発生

Error Message

error: RPC failed; curl 18 transfer closed with outstanding read data remaining fatal: the remote end hung up unexpectedly
#git#クローン#プッシュ#rpc#大規模リポジトリ#httpバッファ

何が起きているのか

リポジトリをクローンまたはプッシュしていて、数秒間は問題なく動いているのに、途中でGitが落ちてしまう:

error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: the remote end hung up unexpectedly

原因はほぼ間違いなくリポジトリのサイズだ。GitのデフォルトHTTPバッファはたった1MBしかない。リポジトリが大きい場合——たとえば何年もの履歴とバイナリアセットを含む500MBのリポジトリ——サーバーがデータを送り始め、バッファが満杯になり、接続が止まり、リモートが切断してしまう。

パーミッションの問題ではない。ファイアウォールでもない。GitのHTTPレイヤーとリモートサーバー間のバッファ/タイムアウトのミスマッチだ。

デバッグ:根本原因を確認する

設定を変更する前に、実際に何が起きているかを確認しよう。

# 現在のhttp.postBuffer設定を確認(デフォルトは1MB = 1048576)
git config --global http.postBuffer

# 出力がない場合は、まだ1MBのデフォルトのまま

次に、完全な詳細ログを有効にしてクローンを実行し、どこで失敗するかを正確に特定する:

GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone https://github.com/your/repo.git 2>&1 | tail -50

RPC failedcurl: (18)、またはtransfer closedを探そう。これら3つの文字列が確認できれば、バッファの問題であることが確定し、以下の修正で解決できる。

解決策1:HTTPポストバッファを増やす(ほとんどのケースに有効)

まずここから始めよう。この1つの設定で、curl 18エラーの約90%が解決される。

# 500MB — ほとんどの大きなリポジトリに対応
git config --global http.postBuffer 524288000

# 1GB — 1GB超のリポジトリや非常に長い履歴の場合
git config --global http.postBuffer 1073741824

クローンまたはプッシュを再試行する:

git clone https://github.com/your/repo.git
# または
git push origin main

**確認方法:**RPCエラーが出なければ成功だ。クローンしたディレクトリの中でgit log --oneline -5を実行して、履歴が正しく取得できているか確認しよう。

解決策2:まずシャロークローンして、その後フル履歴を取得する

コミットが10,000件以上あるリポジトリもある。そういった場合は500MBのバッファでも十分でないことがある。最新のスナップショットだけをクローンして、残りを小さな単位で取得しよう。

# 最新のコミットだけをダウンロード — 速くて軽い
git clone --depth 1 https://github.com/your/repo.git

cd repo

# 完全な履歴を段階的なチャンクで取得する
git fetch --unshallow

--depth 1のクローンでは、全履歴の代わりに数MBしか転送しない。安定した接続でディレクトリに入ってから、--unshallowでバッファを圧迫する大量のバーストではなく、段階的に残りを取得する。

確認方法:--unshallowが完了したら:

git log --oneline | wc -l
# フルコミット数が表示される — 1ではない

解決策3:HTTPSの代わりにSSHに切り替える

curl 18エラーはHTTP経由でのみ発生する。SSHはまったく異なるトランスポートを使用するため、HTTPバッファもRPCレイヤーもcurlも関係ない。

# リモートURLをHTTPSからSSHに切り替える
git remote set-url origin git@github.com:your-username/repo.git

# 変更を確認する
git remote -v

# 再試行
git push origin main
# またはフレッシュにクローン:
git clone git@github.com:your-username/repo.git

SSHはギガバイト単位の転送でも問題なく処理できる。SSHアクセスがある場合、最も信頼性の高い長期的な解決策だ。ポート22をブロックする企業ネットワークでは、SSHをポート443でトンネリングできる場合もある——ssh.github.comの設定についてはGitホストのドキュメントを確認しよう。

解決策4:タイムアウトを無効にして圧縮を下げる

遅い接続(ホテルのWiFi、モバイルホットスポット、VPNのボトルネックなど)では、バッファが満杯になるのではなく、タイムアウト後にサーバーが接続を切断するという別のバージョンのエラーが発生する。2つの設定変更が効果的だ:

# Gitの低速タイムアウトを実質的に無効化する
git config --global http.lowSpeedLimit 0
git config --global http.lowSpeedTime 999999

# zlib圧縮をスキップする — 転送量は増えるがCPUオーバーヘッドが減る
git config --global core.compression 0

lowSpeedLimit 0は転送速度に基づいた中断をGitに行わせないようにする。core.compression 0はファイルサイズをスピードと引き換えにする——各オブジェクトの転送量はやや増えるが、事前の圧縮でCPU時間を消費しない。CPUがボトルネックではない遅い接続では、ほぼ常にメリットが上回る。

低速ネットワークで最良の結果を得るために、これらの設定を解決策1のバッファ増加と組み合わせよう。

解決策5:コミットを小さなバッチに分けてプッシュする

クローンは問題ないのにgit pushが失敗し続ける?おそらく大量のコミットが溜まっているのだろう——1週間以上オフラインで作業した後によくあるケースだ。一度に全部プッシュするのではなく、分割してプッシュしよう。

# プッシュ待ちのコミットを確認する
git log origin/main..HEAD --oneline

# 最初の約100コミットをプッシュする
git push origin <hash-of-100th-commit>:main

# 残りを通常通りプッシュする
git push origin main

実際のハッシュはgit logの出力から取得しよう。未プッシュのコミットが400件ある場合は、タイムアウトする1つの巨大な操作ではなく、100件ずつ4回に分けてプッシュしよう。

修正後の設定を確認する

変更した内容をまとめて確認する:

git config --global --list | grep -E 'http|core.compression'

すべての修正を適用した場合、次のように表示されるはずだ:

http.postbuffer=524288000
http.lowspeedlimit=0
http.lowspeedtime=999999
core.compression=0

どの修正から試すべきか

  • まず試すべき: http.postBufferを増やす(解決策1)——10件中9件はこれで解決する。
  • まだ失敗する場合: --depth 1を使ってから--unshallowする(解決策2)。
  • SSHアクセスがある場合: SSHに切り替える(解決策3)——最も恒久的で信頼性が高い。
  • 遅いまたは不安定な接続の場合: 解決策4のタイムアウト設定とバッファ増加を組み合わせる。
  • プッシュのみの問題の場合: バッチに分けてプッシュする(解決策5)。

得られた教訓

Gitの1MBデフォルトバッファは、ほとんどのリポジトリが小さかった時代の遺産だ。今日のモノレポは2〜5GBに達することもある。10年の歴史、100人のコントリビューター、コミット済みバイナリを持つプロジェクトは、1回のクローン操作で300〜500MBを簡単に転送する——デフォルトバッファで処理できる量の300倍だ。

新しい開発環境をセットアップする際は、大きなものをクローンし始める前にグローバル設定にバッファ設定を追加しておこう。5秒で済み、このような頭痛の種を完全に避けられる。

非常に大きなリポジトリを運用しているチームは、バイナリをメインオブジェクトストアから移動するためにGit LFSも検討すべきだ。また、ルーズオブジェクトをパックするために定期的なgit gc --aggressiveの実行もスケジュールしよう。LFSを使って適切にメンテナンスされたリポジトリは、クローンサイズを80%以上削減できる——転送データが少なければ少ないほど、タイムアウトの問題も大幅に減る。

Related Error Notes