git pushを実行すると次のようなエラーが出て止まることがあります。
$ git push origin main To github.com:user/repo.git ! [rejected] main -> main (non-fast-forward) error: failed to push some refs to 'github.com:user/repo.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. ...
「failed to push some refs to」はpushが拒否されたことを伝える包括メッセージで、その上の行に本当の原因(non-fast-forward/rejected/pre-receive hook declined等)が書かれています。このエラー自体を直接解決するのではなく、上に表示された具体的な理由に応じた対処が必要です。
この記事では、pushが失敗する8つの代表的な原因を整理し、エラー出力から原因を切り分ける診断フローと、それぞれの対処法を解説します。個別の深掘り記事への導線もまとめているので、本記事を「pushエラー総合窓口」として使ってください。
この記事で学べること
- 「failed to push some refs to」が外側メッセージである仕組み
- 出力の「上の行」から本当の原因を特定する方法
- 8パターンの原因と対処法(non-fast-forward/認証/保護ブランチ/サイズ/hook 等)
- 診断フローと、個別詳細記事への導線
--forceを使わずに安全に解決するアプローチ- GitHub/GitLab/BitbucketなどホスティングGit特有のrejection理由
- 同じエラーを繰り返さない予防策
- エラーの正体:外側メッセージと内側原因
- 内側原因と対処の早見表
- 診断フロー:出力からキーワードを探す
- 原因①:non-fast-forward(リモートが先行)
- 原因②:Permission denied(認証エラー)
- 原因③:保護ブランチへの直接push禁止
- 原因④:pre-receive hook が拒否した
- 原因⑤:ファイルサイズ制限超過
- 原因⑥:unrelated historiesによる拒否
- 原因⑦:shallow cloneからのpush拒否
- 原因⑧:タグのconflict/強制更新
- 実践シナリオ:エラーから原因特定まで
- 予防策:pushエラーが起きない運用
- やってはいけない落とし穴
- よくある質問
- 関連記事
- まとめ
エラーの正体:外側メッセージと内側原因
「failed to push some refs」はpushが拒否された時のサマリー行です。内部的な原因はGitがその直前に出力しており、!で始まる行やerror:、remote:プレフィックスで表示されます。
To github.com:user/repo.git ← pushの対象 ! [rejected] main -> main (non-fast-forward) ← 本当の原因はここ error: failed to push some refs to 'github.com:user/repo.git' ← 外側サマリー hint: Updates were rejected because the tip of your current ... ← ヒント
ポイント:対処法は括弧内の内側原因(non-fast-forward・fetch first・pre-receive hook declined等)で決まります。「failed to push some refs」をそのままコピーして検索するのではなく、その行の上を読むのが解決の第一歩です。
内側原因と対処の早見表
以下のいずれかが「failed to push some refs」の背後にあります。自分のエラー出力からキーワードを探して対応セクションへ飛んでください。
原因別の詳細記事
診断フロー:出力からキーワードを探す
push時のエラーを読む手順を整理します。
# STEP 1: 失敗したpushを再実行して全文を取得 git push 2>&1 | tee /tmp/push-error.log # STEP 2: "rejected" 行の括弧内キーワードを確認 grep -E "rejected|error|hint|remote" /tmp/push-error.log # STEP 3: リモートとローカルの関係を把握 git fetch origin git log --oneline --graph --all --decorate -20 # STEP 4: ahead/behind 件数を確認 git rev-list --left-right --count origin/main...HEAD # 出力: "3 2" ← リモートが3件先行、ローカルが2件固有
ポイント:エラーメッセージの括弧内とremote:プレフィックスの行が最も重要です。remote:から始まる行はサーバー側(GitHub等)からの応答で、保護ブランチ・LFS・pre-receive hookの判定結果が書かれています。
原因①:non-fast-forward(リモートが先行)
もっとも頻出する原因です。自分がローカルで作業している間に、他メンバーがリモートにpushして先行している状態で起きます。
! [rejected] main -> main (non-fast-forward) error: failed to push some refs to '...' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart.
# リモートの変更を取り込んで履歴を整理 git pull --rebase origin main # コンフリクトが出たら解消 git add . git rebase --continue # 改めてpush git push origin main
注意:--rebaseを使わずに普通にgit pullすると、マージコミットが増えて履歴が汚れがち。個人ブランチならpull --rebase、共有ブランチならPR経由が無難です。詳しくは“non-fast-forward”で拒否されたときの解決方法を参照。
原因②:Permission denied(認証エラー)
SSH鍵やPersonal Access Token(PAT)が無効/期限切れ/未登録の場合です。
git@github.com: Permission denied (publickey). fatal: Could not read from remote repository. error: failed to push some refs to '...'
# SSH疎通確認 ssh -T git@github.com # HTTPS形式ならトークン再発行 git remote set-url origin https://TOKEN@github.com/USER/REPO.git # または credential.helper を設定 git config --global credential.helper store
SSH鍵の登録手順や切り分けは「Permission denied (publickey)」エラーの原因と解決方法で詳しく解説しています。
原因③:保護ブランチへの直接push禁止
GitHub等でBranch protection rulesが設定されたブランチには管理者以外が直接pushできません。特にmain/developが保護されているケースが多いです。
remote: error: GH006: Protected branch update failed for refs/heads/main. remote: error: Required status check "ci/build" is expected. ! [remote rejected] main -> main (protected branch hook declined) error: failed to push some refs to '...'
保護ブランチの対処
- 作業ブランチを切ってPRを作成(推奨)
- CIの必須チェックをパスさせる
- 必要レビュー数を満たす
- 管理者権限で一時解除するのは最終手段
ポイント:保護ブランチ設定は「事故予防」として価値が高い仕組みです。直接pushできないからといって無効化するのではなく、「PR作成→レビュー→マージ」の標準フローに乗せるのが長期的に安定運用につながります。
原因④:pre-receive hook が拒否した
サーバー側のフックがpushの内容をチェックし、ポリシーに反するとrejectします。大きなファイル・コミットメッセージ形式違反・lintエラーなど内容は様々です。
remote: pre-receive hook declined ! [remote rejected] main -> main (pre-receive hook declined) error: failed to push some refs to '...' # より親切なフックだと理由も表示される remote: Error: commit message must start with Conventional Commits prefix
よくあるpre-receive ruleの例
- コミットメッセージ形式(Conventional Commits 等)の強制
- ファイルサイズ上限の強制
- DCO(Signed-off-by)必須
- 禁止パターンのファイル(.env 等)を含まない
- 管理者以外は強制push禁止
# メッセージを修正(直前のcommit) git commit --amend -m "feat: 適切なprefix付きメッセージ" # Signed-off-by 追加 git commit --amend --signoff --no-edit # 巨大ファイルをLFSへ git lfs track "*.psd" git add .gitattributes
コミットメッセージ整形はコミットメッセージの変更方法を参照。
原因⑤:ファイルサイズ制限超過
GitHubは100MBを超えるファイルをpushしようとするとrejectします。GitHub Free/Proでリポジトリサイズ1GBの推奨もあります。
remote: error: File data/model.bin is 245.00 MB; this exceeds GitHub's file size limit of 100.00 MB ! [remote rejected] main -> main (pre-receive hook declined) error: failed to push some refs to '...'
# Git LFSをインストール git lfs install # 対象パターンをLFS管理に git lfs track "*.bin" "*.psd" "*.mp4" git add .gitattributes # 既存履歴から巨大ファイルを除く(git filter-repo) pip install git-filter-repo git filter-repo --strip-blobs-bigger-than 50M # 改めてLFS化してcommit → push git add data/model.bin git commit -m "feat: model.bin をLFSで管理" git push
注意:filter-repoは履歴全体を書き換える破壊的操作です。全メンバーの再cloneが必要になるため、実行前にチームに周知してください。詳細は履歴に含まれる機密情報を完全に削除する方法を参照。
原因⑥:unrelated historiesによる拒否
pushしようとするブランチとリモートが共通祖先を持たない場合、push時点でrefused される(GitHubは受付けることもあるが、push後のpull時にエラー)。
# 共通祖先の有無を診断 git merge-base HEAD origin/main # unrelatedならマージで統合 git pull origin main --allow-unrelated-histories git push
詳細は「refusing to merge unrelated histories」エラーの対処法を参照。
原因⑦:shallow cloneからのpush拒否
CI等でgit clone --depth=1したリポジトリから直接pushしようとすると、完全履歴を持たないためrefされることがあります。
# shallow状態を確認 git rev-parse --is-shallow-repository # true なら shallow # 完全履歴に戻す git fetch --unshallow # すべてのリモートを深めたい場合 git fetch --all --unshallow # 改めてpush git push origin main
shallow cloneの扱い
- CI/CDの高速化目的で
--depth=1が使われる - push側で完全履歴が必要な場合は
fetch --unshallowで展開 - GitHub ActionsのcheckoutV4は
fetch-depth: 0オプションで全履歴取得可能
原因⑧:タグのconflict/強制更新
既存タグと同じ名前のタグをpushする場合、デフォルトで拒否されます。
! [rejected] v1.0.0 -> v1.0.0 (already exists) error: failed to push some refs to '...' hint: Updates were rejected because the tag already exists in the remote.
# 同じタグをどうしても上書きしたい場合 git push --force origin v1.0.0 # ただしタグの上書きは通常禁忌 # 新しいバージョン番号にする方が無難 git tag v1.0.1 git push origin v1.0.1 # 全タグを一度にpush git push origin --tags
注意:タグはリリースポイントの固定参照として機能します。一度pushしたタグを上書きすると、それを使っているCI/デプロイ/参照している他リポとの整合性が崩れます。やむを得ない場合以外は、バージョン番号を新しくするほうが安全です。
実践シナリオ:エラーから原因特定まで
シナリオ① 朝いちばんのpushで rejected
git push # → (non-fast-forward) git fetch origin git log --oneline origin/main..HEAD # ローカル固有コミット git log --oneline HEAD..origin/main # リモート固有コミット git pull --rebase origin main git push
シナリオ② main保護でrejected
# 直接mainにpushしてreject git push origin main # → (protected branch hook declined) # 直前のコミットを新ブランチに移動 git switch -c feature/from-main git push -u origin feature/from-main # main を取り消し git switch main git reset --hard origin/main # ローカル側のmainをリモートに合わせる # PRでレビュー → マージ
シナリオ③ 巨大ファイル混入でreject
# エラー確認 git push # remote: error: File data/video.mp4 is 120.00 MB; exceeds 100MB # LFSセットアップ git lfs install git lfs track "*.mp4" git add .gitattributes # 既に履歴に入ってしまった場合は filter-repo で除去 git filter-repo --path data/video.mp4 --invert-paths # LFS経由で再追加 cp /backup/video.mp4 data/video.mp4 git add data/video.mp4 git commit -m "feat: video.mp4 をLFS管理で追加" git push
シナリオ④ 新規リポで初push rejected
git push -u origin main # → rejected (fetch first) git pull origin main --allow-unrelated-histories # コンフリクト解消 git push -u origin main
予防策:pushエラーが起きない運用
日常運用のコツ
- pull.rebase = true:pull時にrebaseを優先して不要なマージコミットを抑制
- push.autoSetupRemote = true(Git 2.37+):初回
-u忘れ防止 - Branch protection:保護ブランチ設定で誤pushを物理的に防止
- pre-commit hook:commit段階で大きいファイル・typo・lint違反を止める
- Git LFSを早めに導入:大きなファイルはサイズ制限に触れる前にLFS化
- .gitignore整備:生成物・機密が意図せず入らないように
- PRベースのマージ運用:直接pushの機会を減らして事故予防
# pullでrebaseを自動適用 git config --global pull.rebase true # 新ブランチ初回pushで自動upstream設定 git config --global push.autoSetupRemote true # force pushは force-with-lease を既定に git config --global alias.fp 'push --force-with-lease' # pre-commitフレームワーク pip install pre-commit pre-commit install
やってはいけない落とし穴
エラー詳細を読まずに –force で押し切る
「pushできないから強制」でgit push -fすると、リモート側の履歴を破壊します。他メンバーの作業が消えて責任問題にも発展しかねません。まずは必ず原因を診断しましょう。どうしてもforce pushが必要なら--force-with-leaseを使って、他人の新規pushを上書きしない安全装置を入れてください。
外側メッセージだけで検索する
「failed to push some refs to」でGoogle検索すると大量の記事が出ますが、本当に必要なのは括弧内のキーワード(non-fast-forward等)です。時間をかけて誤った対処を試すより、エラー出力全文を読んで正しい原因を特定してください。
保護ブランチをforce pushで突破
管理者権限がある場合にBranch protectionを一時無効にしてforce pushする運用は危険です。CIが通っていないコード・レビュー未了の変更がmainに入る可能性があり、本番障害の原因になります。緊急時以外は必ずPR経由で。
サイズ超過ファイルを普通にコミットし直す
100MB超のファイルをコミット→push rejected→ファイル削除→再コミット→再push、としても過去のコミットに巨大ファイルが残っているのでrejectは直りません。履歴から巨大ファイルを削除する(filter-repo)か、ブランチを切り直して新履歴からやり直す必要があります。
fetch前のahead/behind判断
git log --oneline origin/main..HEADの結果はローカルのorigin/main追跡情報を元にします。git fetchせずに判断すると古いスナップショットで誤認するので、必ずgit fetchしてから差分確認してください。
よくある質問
GIT_TRACE=1 git pushで詳細ログ、git push --verboseで出力を増やして再実行してください。CIログでは上方向にスクロールするとremote:行が見つかります。--force-with-leaseで上書き、共有ブランチならpull/mergeで取り込みが原則。git filter-repo --strip-blobs-bigger-than 50Mが現在のベストプラクティス。全メンバーの再cloneが必要な破壊的操作ですが、リポジトリを軽量化するにはこれ以外に確実な方法がありません。詳細は履歴に含まれる機密情報を完全に削除する方法を参照。git pull --rebase→git pushで解決できます。force pushが必要なのは「amend後」「rebase後」「reset後」などローカルで履歴書き換えをした時だけ。共有ブランチではそもそも履歴書き換えを避ける運用が基本です。refs/heads/mainはmainブランチ、refs/tags/v1.0はタグv1.0を指します。「some refs」は「複数のref」を意味し、同時に複数ブランチ/タグをpushしようとして一部が失敗した場合も出ます。関連記事
- 【Git】pushしようとしたら”non-fast-forward”で拒否されたときの解決方法 — 最頻出原因の深掘り
- 【Git】「Permission denied (publickey)」エラーの原因と解決方法 — 認証エラーの対処
- 【Git】「refusing to merge unrelated histories」エラーの対処法 — 共通祖先なしマージ
- 【Git】「does not appear to be a git repository」エラー — リモート設定関連
- 【Git】履歴に含まれる機密情報を完全に削除する方法 — filter-repoによる履歴クリーン
- 【Git】pushを取り消す方法 — pushが成功したあとの対処
- 【Git】コミットメッセージの変更方法 — commit-msgフック対応
- 【Git】よく使うgitコマンドまとめ — 日常コマンドの早見表
まとめ
- 「failed to push some refs to」は外側のサマリーで、本当の原因は上の行にある
- 括弧内キーワード(non-fast-forward/protected branch/pre-receive hook declined等)を読む
- 8パターンの原因別に対処:
pull --rebase/認証更新/PR経由/フック対応/LFS/--allow-unrelated-histories/unshallow/タグ整理 --forceは最終手段、日常使いは--force-with-leaseで安全確保- 予防:
pull.rebase=true/push.autoSetupRemote=true/Branch protection/pre-commit/LFS - 巨大ファイル混入は
filter-repoで履歴から除去、LFS化に移行 - 個別の深掘りは原因別の関連記事を参照
このエラーに出会ったら、まず慌てずにエラー全文を読むことが最短ルートです。failed to push some refsの上の行に必ず本当の原因が書かれており、括弧内の1フレーズで対処法が決まります。今回のパターン別対処と診断フローを手元に置いておけば、多くのケースで慌てずに解決できるはず。--forceに頼らない運用を心掛け、チーム開発を安全に進めていきましょう。
