【Git】「failed to push some refs to」エラーの原因と対処法|8パターン診断と個別対策完全ガイド

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-forwardrejectedpre-receive hook declined等)が書かれています。このエラー自体を直接解決するのではなく、上に表示された具体的な理由に応じた対処が必要です。

この記事では、pushが失敗する8つの代表的な原因を整理し、エラー出力から原因を切り分ける診断フローと、それぞれの対処法を解説します。個別の深掘り記事への導線もまとめているので、本記事を「pushエラー総合窓口」として使ってください。

この記事で学べること

  • 「failed to push some refs to」が外側メッセージである仕組み
  • 出力の「上の行」から本当の原因を特定する方法
  • 8パターンの原因と対処法(non-fast-forward/認証/保護ブランチ/サイズ/hook 等)
  • 診断フローと、個別詳細記事への導線
  • --forceを使わずに安全に解決するアプローチ
  • GitHub/GitLab/BitbucketなどホスティングGit特有のrejection理由
  • 同じエラーを繰り返さない予防策
スポンサーリンク

エラーの正体:外側メッセージと内側原因

「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-forwardfetch firstpre-receive hook declined等)で決まります。「failed to push some refs」をそのままコピーして検索するのではなく、その行の上を読むのが解決の第一歩です。

内側原因と対処の早見表

以下のいずれかが「failed to push some refs」の背後にあります。自分のエラー出力からキーワードを探して対応セクションへ飛んでください。

内側のキーワード 原因 推奨対処
non-fast-forward リモートが自分より先行 pull --rebase→再push
fetch first 上と同じ(non-fast-forwardの別表現) 同上
Permission denied SSH/トークン認証失敗 鍵登録/トークン更新
protected branchrefusing to 保護ブランチへの直接push禁止 PR経由/管理者に依頼
pre-receive hook declined サーバー側フックで拒否 フック条件を満たすよう修正
file too largeexceeds .. limit ファイルサイズ制限超過(100MB等) LFS化/履歴から削除
shallow update not allowed shallow cloneからのpush unshallowで完全化
refusing to merge unrelated histories 共通祖先の無い履歴 --allow-unrelated-histories

診断フロー:出力からキーワードを探す

push時のエラーを読む手順を整理します。

エラー診断の3ステップ
# 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して先行している状態で起きます。

non-fast-forward の典型エラー
 ! [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.
対処:pull –rebase → push
# リモートの変更を取り込んで履歴を整理
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エラーなど内容は様々です。

pre-receive hook の典型例
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 '...'
対処:LFS化と履歴クリーン
# 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されることがあります。

対処:履歴を完全化してからpush
# 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

同僚が先にpushしていたパターン
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

ブランチを切ってPR作成
# 直接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

LFS化して解決
# エラー確認
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

GitHub側READMEとunrelated
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してから差分確認してください。

よくある質問

Qfailed to push some refs to だけが出ていて内側が見えない
AGitやCIツールの表示設定で一部ログが切られている可能性があります。GIT_TRACE=1 git pushで詳細ログ、git push --verboseで出力を増やして再実行してください。CIログでは上方向にスクロールするとremote:行が見つかります。
Qpull したくない、でもpush したい
A履歴的に無理な願望です。non-fast-forwardの場合、リモートに無いローカル変更を同期せずにpushすると他メンバーの変更を上書きします。個人ブランチなら--force-with-leaseで上書き、共有ブランチならpull/mergeで取り込みが原則。
Q古い大きなファイルをGitから消す最短手段は?
Agit filter-repo --strip-blobs-bigger-than 50Mが現在のベストプラクティス。全メンバーの再cloneが必要な破壊的操作ですが、リポジトリを軽量化するにはこれ以外に確実な方法がありません。詳細は履歴に含まれる機密情報を完全に削除する方法を参照。
Qremote: で始まる行だけ赤く見える
AGitHub等のサーバーが出しているメッセージです。赤くても「即危険」ではなく注意喚起であることが多いので、内容を読んで判断しましょう。例:「大きなファイルですがLFS推奨」は警告だけでpushは成功しているケースもあります。
Q保護ブランチでもたまに直接pushしたい
A原則避けるべきですが、緊急時は管理者権限で一時解除→push→保護再適用の流れ。GitHubの”Require a pull request before merging”を一時的にオフにする手順。やむを得ない事情が多いチームならCODEOWNERSやbranch protection設定を見直してください。
Q強制pushせずに解決したい
Aほとんどのケースはgit pull --rebasegit pushで解決できます。force pushが必要なのは「amend後」「rebase後」「reset後」などローカルで履歴書き換えをした時だけ。共有ブランチではそもそも履歴書き換えを避ける運用が基本です。
Qrefs とは何を指す?
AGitの「reference」の略で、ブランチ/タグ/HEADの総称です。refs/heads/mainはmainブランチ、refs/tags/v1.0はタグv1.0を指します。「some refs」は「複数のref」を意味し、同時に複数ブランチ/タグをpushしようとして一部が失敗した場合も出ます。

関連記事

まとめ

  • 「failed to push some refs to」は外側のサマリーで、本当の原因は上の行にある
  • 括弧内キーワード(non-fast-forward/protected branch/pre-receive hook declined等)を読む
  • 8パターンの原因別に対処:pull --rebase/認証更新/PR経由/フック対応/LFS/--allow-unrelated-historiesunshallow/タグ整理
  • --forceは最終手段、日常使いは--force-with-leaseで安全確保
  • 予防:pull.rebase=truepush.autoSetupRemote=true/Branch protection/pre-commit/LFS
  • 巨大ファイル混入はfilter-repoで履歴から除去、LFS化に移行
  • 個別の深掘りは原因別の関連記事を参照

このエラーに出会ったら、まず慌てずにエラー全文を読むことが最短ルートです。failed to push some refsの上の行に必ず本当の原因が書かれており、括弧内の1フレーズで対処法が決まります。今回のパターン別対処と診断フローを手元に置いておけば、多くのケースで慌てずに解決できるはず。--forceに頼らない運用を心掛け、チーム開発を安全に進めていきましょう。