症状
git commit --amend でコミットを修正した後、git push が rejected される。
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'origin/main'
結論:まずこれを確認
--amendはコミットを「書き換える」ため、リモートと履歴が分岐する- 解決には
git push --force-with-leaseを使う - 他の人と共有しているブランチでは使用禁止
操作フロー
flowchart TD
A[amend後にpushがreject] --> B{ブランチは自分専用?}
B -->|Yes| C[git push --force-with-lease]
B -->|No| D[force pushは危険]
D --> E[新しいコミットで修正を追加]
C --> F{pushできた?}
F -->|Yes| G[完了]
F -->|No| H[リモートが更新されている]
H --> I[git fetch して状況確認]
よくある原因
- 履歴の分岐:
--amendは新しいコミットを作成し、古いコミットを置き換えるため - リモートに既にpush済み: amend前のコミットがリモートに存在する
- 他の人がpush済み: 自分がfetch後に他の人がpushしている
- ブランチ保護ルール: GitHubでforce pushが禁止されている
- 権限不足: リポジトリへのwrite権限がない
- 間違ったリモート指定: originが期待と異なるリポジトリを指している
操作手順
ステップ1: 現在の状態を確認する
git status
🔍 チェックポイント: 「Your branch and ‘origin/xxx’ have diverged」と表示されれば、履歴が分岐している
ステップ2: リモートとの差分を確認する
git log --oneline origin/main..HEAD
git log --oneline HEAD..origin/main
🔍 チェックポイント:
- 1つ目のコマンドでローカルにしかないコミットが表示される
- 2つ目のコマンドでリモートにしかないコミットが表示される
- 2つ目が空なら、自分のamendのみが原因
ステップ3: ブランチが自分専用か確認する
git log --oneline -5 origin/main
🔍 チェックポイント: コミットの作者が全て自分であれば、force pushしても他者への影響は少ない
ステップ4: force push を実行する(自分専用ブランチの場合)
git push --force-with-lease
🔍 チェックポイント:
--force-with-leaseは--forceより安全- リモートが予期せず更新されていた場合は失敗する
ステップ5: 共有ブランチの場合は新規コミットで対応する
# amendを取り消して元のコミットに戻す
git reflog
# 該当するHEAD@{n}を探す
git reset --soft HEAD@{1}
git commit -m "修正内容を説明するメッセージ"
git push
🔍 チェックポイント: 履歴を書き換えずに、新しいコミットとして修正を追加する
NG行動(やってはいけないこと)
- 共有ブランチで
git push --force: 他の人の作業が消える可能性がある --forceを安易に使う:--force-with-leaseを使う習慣をつける- 確認せずにforce push:
git logで差分を確認してから実行する - mainブランチへのforce push: 多くのプロジェクトでは禁止されている
- リモートの状態を確認せずに操作:
git fetchで最新状態を取得してから判断する
よくある質問(FAQ)
Q1: --force と --force-with-lease の違いは?
A: --force は無条件で上書きする。--force-with-lease は、ローカルが把握しているリモートの状態と実際のリモートが一致する場合のみ上書きする。他の人がpushしていた場合は失敗するため、より安全。
Q2: ブランチ保護でforce pushできない場合は?
A: GitHubの Settings > Branches > Branch protection rules でforce pushが禁止されている。管理者に相談するか、新しいコミットで修正を追加する方法を取る。
Q3: 間違えてforce pushしてしまった場合の復旧方法は?
A: git reflog でforce push前のコミットハッシュを探し、git push --force origin <hash>:main で復元できる可能性がある。ただし、他の人がfetchしていた場合は完全な復旧は難しい。
関連するトラブル
準備中
解決しない場合
- Git公式ドキュメント - git-push
- GitHub - About protected branches
- 確認すべきログ:
git reflog、git log --oneline --all --graph - 次に調べるキーワード: 「git force push 復旧」「git reflog 使い方」「GitHub branch protection」