DevToolBox

git push rejected (non-fast-forward) の直し方

最終更新日: 2026-04-19公開日: 2026-04-19執筆: DevToolBox編集部

! [rejected] main -> main (non-fast-forward) は、リモートの履歴が 自分のローカルと直線的に繋がらない時に出ます。闇雲に --force すると他人の コミットが消えるため、段階的な直し方を押さえましょう。

non-fast-forward means the remote has commits yours don't. Blind--force can erase teammates' work; use --force-with-leaseinstead.

TL;DR

1. 原因の切り分け / Diagnose

git fetch origin
git log --oneline origin/main..HEAD   # ローカル側の独自コミット
git log --oneline HEAD..origin/main   # リモート側の独自コミット

両方に独自コミットがあれば「真の分岐」、自分側だけなら「fast-forward 可能」、 相手側だけなら単なる「pull 忘れ」です。

2. ケース別の直し方 / Fix by case

状況 / Situationコマンド / Command備考 / Notes
同じブランチに他人が pushgit pull --rebase && git push衝突解決後 --continue
rebase / commit --amend したgit push --force-with-lease自分の feature branch 限定
誤ったコミットを残したくないgit reset --hard origin/main 後 pushローカル変更は消える。先に git stash
保護ブランチで弾かれるPR 経由に切り替えmain は force push 禁止が正解

3. --force-with-lease を使う理由 / Why --force-with-lease

--force は「上書き」。他の人が push した直後だと、その変更を黙殺して自分の履歴に 置き換えます。--force-with-lease は「私が最後に見たリモート状態と一致する場合に限り、 上書きを許す」という条件付き強制。事故を自動検知して止まります。

# ❌ 危険
git push --force

# ✅ 安全
git push --force-with-lease

4. 予防策 / Prevention

5. rebase中にコンフリクトが起きたら / Resolving conflicts during rebase

git pull --rebaseで自分のコミットとリモートの新しいコミットが同じ行を変更していると、 コンフリクトで止まります。落ち着いて次の手順で進めます。

git pull --rebase
# コンフリクト発生時:
git status                    # コンフリクト中のファイルを確認
# ファイルを編集して <<<<<<< ======= >>>>>>> を解消
git add <解決したファイル>
git rebase --continue          # 次のコミットへ進む

# うまくいかない場合は最初からやり直せる
git rebase --abort              # rebase開始前の状態に戻る

git rebase --abortは安全な逃げ道です。コンフリクトが複雑で判断に迷ったら、 一度中断してリモートの変更内容を確認してから再度試すこともできます。

6. --force-with-leaseの仕組みを正確に理解する / How force-with-lease actually works

--force-with-leaseは「自分が最後にfetchした時点のリモート状態」と、今実際にリモートにある状態を比較し、一致する場合だけ push を許可します。 つまり、自分が知らない間に誰か他の人が push していれば、その差分を検知して自動的に拒否します。

# 手順のイメージ
git fetch origin                      # (1)最新のリモート状態を取得
# ...ローカルでrebaseやamendを行う...
git push --force-with-lease           # (2)fetch時点のorigin/mainと現在のorigin/mainを比較

# (2)の直前に他の人が push していた場合:
# "stale info" 等のエラーで拒否される(自分のforceが他人のコミットを消すのを防止)

この仕組みのため、--force-with-leaseを使う直前には必ず最新のfetchを 行っておくことが重要です。古いfetch情報のまま実行すると、本来検知すべき他人の変更を 見逃す可能性があります。

7. GitHub/GitLabでのブランチ保護設定 / Branch protection settings

コマンド運用だけに頼らず、リポジトリ側でもmain/masterへの直接pushや force pushを禁止しておくと事故を構造的に防げます。

保護ブランチに force push しようとすると、ローカルの--force-with-leaseすら サーバ側で拒否されるため、個人のミスとチームのルール違反の両方を防げます。

8. English summary

A non-fast-forward rejection means your local branch and the remote have diverged. If a teammate pushed first, run git pull --rebase then push. If you rewrote history locally (rebase, amend), use git push --force-with-lease — never plain--force on a shared branch, as it silently overwrites other people's commits. On main/master, protect the branch and push via pull requests only.

よくある質問 / FAQ

non-fast-forward とは何?
リモートのブランチ履歴が、自分のローカルの履歴の直線的な延長ではない状態。他の人の push が先にあった、または自分が rebase/amend した時に発生します。
What is non-fast-forward?
The remote branch has commits your local branch doesn't, so your push would overwrite history. Typically caused by someone else pushing first, or by a local rebase/amend.
--force と --force-with-lease の違い
--force は無条件上書き。--force-with-lease はリモートが自分の知っている状態と一致する場合だけ書き換えるため、他人のpush を消し去る事故を防げます。共同作業では必ず --force-with-lease。

関連ツール / Related tools

関連ガイド / Related guides