git push rejected (non-fast-forward) の直し方
! [rejected] main -> main (non-fast-forward) は、リモートの履歴が 自分のローカルと直線的に繋がらない時に出ます。闇雲に --force すると他人の コミットが消えるため、段階的な直し方を押さえましょう。
non-fast-forwardmeans the remote has commits yours don't. Blind--force can erase teammates' work; use --force-with-leaseinstead.
TL;DR
- 他人の push が先にあった →
git pull --rebaseしてから push - 自分が rebase/amend した →
git push --force-with-lease - main / master への force push は原則禁止(保護ブランチ設定)
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 |
|---|---|---|
| 同じブランチに他人が push | git 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-lease4. 予防策 / Prevention
- ブランチ保護で
main/masterは force push 禁止 - チーム内では「個人ブランチ以外は force 禁止」のルールを明文化
git config --global pull.rebase trueでデフォルトを rebase に
5. 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--forceon a shared branch, as it silently overwrites other people's commits. On main/master, protect the branch and push via pull requests only.