4.

git denying non-fast-forward refs/heads/master の原因と対処(pull

編集
この記事の要点
  • git push 時に 「denying non-fast-forward refs/heads/master (you should pull first)」 が表示される
  • 原因: リモートにローカルに無いコミットがある、または git rebase / git commit --amend でローカルが履歴書き換えしている
  • 通常の対処: git pull --rebase でリモート最新を取り込んで再 push
  • 完全に上書きしたい場合: git push --force-with-lease(推奨)/ --force(危険)
  • GitHub / GitLab の保護ブランチ設定で拒否されている場合は、保護ルールの見直しまたは PR 経由のマージが必要

このエラーの概要

git push 実行時に次のような拒否メッセージが返ってきます:

$ git push origin master
To gitserver:repo.git
 ! [remote rejected] master -> master (denying non-fast-forward refs/heads/master (you should pull first))
error: failed to push some refs to 'gitserver:repo.git'

# GitHub の場合の別パターン
 ! [rejected]        master -> master (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. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.

「fast-forward でない」とは、リモートの履歴を直線的に進める形ではない push という意味です。リモートに自分が持っていないコミットがある(誰かが先に push した)、または自分が amend / rebase でローカルを書き換えた、のどちらかです。

原因の典型

状況意味対処
他の人が先に push したリモートが進んでいるgit pull --rebase + push
git commit --amend 後 push履歴書き換え--force-with-lease
git rebase 後 push履歴書き換え--force-with-lease
git reset --hard で過去戻し履歴書き換え--force-with-lease
保護ブランチで拒否GitHub/GitLab 設定PR 経由 / 保護ルール変更

対処 1: pull --rebase で取り込み再 push(通常はこれ)

他の人が先に push しただけなら、リモート最新を取り込んで自分のコミットを上に積み直します:

# リモートの変更を取り込む(rebase で履歴をきれいに)
git pull --rebase origin master

# コンフリクトが出たら解決
# ファイルを編集 → git add → git rebase --continue

# 再 push
git push origin master

merge コミットを許容するなら git pull でも可(merge コミットができます)。

対処 2: --force-with-lease で安全に強制 push

自分が rebase / amend で履歴を書き換えた場合は強制 push が必要です。--force は他人の作業を吹き飛ばす危険があるため、--force-with-lease を使います:

# 推奨: --force-with-lease
# リモートが自分が認識しているコミットから動いていない時のみ push 成功
git push --force-with-lease origin master

# 失敗した場合(他人が push 済 = 上書きすると消える)
# ! [rejected] master -> master (stale info)
# このときは pull --rebase で取り込んでから再度 force-with-lease

# 非推奨: 完全強制(他人の push があっても消す)
git push --force origin master

--force-with-lease は「リモートが自分が最後に見た状態と同じなら上書き」というロジックで、他人の push を踏み潰すリスクを下げます。

対処 3: なぜ履歴書き換えになったか確認

# ローカルとリモートのログを比較
git log --oneline origin/master..master    # ローカルにあってリモートに無い
git log --oneline master..origin/master    # リモートにあってローカルに無い

# 直近の reflog(操作履歴)
git reflog -10

# amend / rebase 後はコミット SHA が変わる
git log --oneline -5

対処 4: 保護ブランチで拒否されている場合

GitHub / GitLab / Bitbucket では master / main保護ブランチに指定し、直接 push を禁止できます。この場合のメッセージは少し違います:

remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: At least 1 approving review is required by reviewers with write access.

対処は運用方針による:

  • 正攻法: 別ブランチに push し Pull Request を作成、レビュー後マージ
  • 保護ルール変更: GitHub → Settings → Branches → Branch protection rules を編集(管理者権限必須)
  • 緊急対応: 保護ルールを一時無効化(記録に残る、推奨されない)

force 推奨ガイドライン

シナリオ推奨手段
個人ブランチで自分しか触らない--force-with-lease OK
feature ブランチを複数人で共有事前にチームへ周知 → --force-with-lease
master / main / develop原則禁止。どうしてもなら全員に通知
公開 OSS の main絶対禁止(コミット ID で参照する人がいる)

force push の事故から復旧

強制 push で他人のコミットを上書きしてしまった場合、リモートには履歴が残らなくても誰かのローカルか reflogに残っていれば復旧できます:

# 元のコミットを持っている人がいたら、その人のローカルから push
# または GitHub の場合 Events / Activity から SHA を発掘可能

# reflog から
git reflog
# abc123 HEAD@{2}: commit: lost commit
git reset --hard abc123
git push --force-with-lease origin master

FAQ

Q: pull --rebase でコンフリクトが大量に出る
A: 「ローカル変更が少ない」「リモート変更が少ない」どちらが少ない側に揃えるか判断。少ない方をcherry-pick し直す方が早いことも。git rebase --abort でやり直し可能。

Q: --force-with-lease でも拒否される
A: 自分が最後に fetch してから他人が push した状態。git fetch で最新を取得して再判断してから force するか、pull --rebase で取り込んでください。

Q: 履歴を書き換えずに push したい
A: git pull --no-rebase(merge 戦略)で取り込めば履歴は分岐するが上書きにはなりません。merge コミット 1 つで両方の作業を保持できます。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. fatal: remote origin already exists.
  2. fatal: '~' does not appear to be a git repository
  3. Cannot rebase: You have unstaged changes. Please commit or stash them.
  4. remote: error: denying non-fast-forward refs/heads/master (you should pull first)
  5. error: pathspec ... did not match any file(s) known to git.
  6. The following untracked working tree files would be overwritten by checkout
  7. fatal: Not a valid object name: 'master'.
  8. Unlink of file 'ファイル名' failed. Should I try again? (y/n)
  9. Another git process seems to be running in this repository, ~
  10. error: Your local changes to the following files would be overwritten by checkout: