Git push 出現「the remote end hung up unexpectedly」:先判斷 HTTP 400 的位置

這是一次推送含有套件與較多變更的專案時留下的紀錄。當時終端機顯示物件已列舉、壓縮並開始寫入,最後卻出現:

error: RPC failed; HTTP 400 curl 22 The requested URL returned error: 400
fatal: the remote end hung up unexpectedly

這類輸出很容易讓人以為「本機 Git 壞了」。其實前面的壓縮與寫入只代表本機已把 pack 檔準備好;HTTP 400 則表示伺服器或中間的反向代理已拒絕這次 HTTP 請求。排查時,先把問題分成遠端設定、網路/驗證、物件大小與伺服器規則四類,比直接調大參數可靠。

先確認不是推到錯的遠端

git remote -v
git status
git ls-remote origin

git remote -v 用來確認 fetch 與 push URL;git ls-remote origin 可以在不推送物件的情況下驗證遠端可否讀取。若這一步就失敗,先處理帳號授權、存取權限、HTTPS Proxy 或 SSH 設定,而不是檢查 pack 檔。

釐清「寫到一半失敗」代表什麼

遇到 HTTP 400 時,常見原因不是 Git 協定本身,而是託管平台、Web Server 或反向代理對請求大小、逾時、身分驗證或 URL 的限制。這次輸出中的 Writing objects: ... 7.85 MiB 只是當下已寫出的量,不能單獨證明是容量上限;應回頭查看遠端平台與 Proxy 的紀錄,找同一時間的拒絕原因。

本機端可先盤點倉庫大小與歷史物件:

git count-objects -vH
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectsize) %(rest)' | sort -k2n

若找到不該進版控的大型二進位檔、建置產物或壓縮檔,應從目前提交與歷史一併處理,並以 .gitignore 阻止再次加入。只是刪除工作目錄裡的檔案,舊物件仍可能留在歷史中。

http.postBuffer 不是預設修法

舊的排錯筆記曾建議把 http.postBuffer 設得很大。這個做法並不會解除伺服器端的請求大小或逾時限制,也可能讓團隊誤以為問題已被修好。若真的要調整 Git 用戶端設定,應先記錄原值與設定來源:

git config --show-origin --get-all http.postBuffer
git config --show-origin --get-all http.version

只有在遠端服務的文件或管理者已確認需要用戶端相容性設定時,才做範圍最小的調整,並在一次成功推送後重新驗證。比較值得優先修正的,通常是 Proxy 限制、伺服器紀錄指出的請求問題,或是不應存在於 Git 歷史中的大型檔案。

完成後的驗證

修正後以正常的 git push origin <branch> 推送一次,再到遠端確認 commit SHA、分支與檔案內容都一致。若失敗仍是 HTTP 400,保留完整時間、遠端 URL(不含憑證)與伺服器回應交給平台管理者,會比只提供最後一行錯誤更容易定位。

參考資料

Author image
關於 Richard Zheng
About me 喜歡爬山,瑜伽,溜冰,喜歡新奇的事,最喜歡的還是寫程式帶來的成就感,對於資訊會不斷的出現新事物也能抱持好奇與熱忱。近期開始將學習的心得寫在Blog,發現思路更清晰也加深了記憶。 紙上得來終覺淺,絕知此事要躬行