症状

git push 実行時に以下のようなエラーが表示される。

    ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart.
  

結論:まずこれを確認

  1. リモートに自分以外のコミットがないか git fetch && git log origin/main..HEAD で確認
  2. ある場合は git pull --rebase でリモートの変更を取り込む
  3. ない場合は意図せず履歴が書き換わっていないか確認

操作フロー

    flowchart TD
    A[git push が rejected] --> B{git fetch して確認}
    B --> C{リモートに新しいコミットあり?}
    C -->|Yes| D[git pull --rebase を実行]
    C -->|No| E{ローカルで履歴を書き換えた?}
    D --> F[コンフリクトあり?]
    F -->|Yes| G[コンフリクト解消]
    F -->|No| H[git push を再実行]
    G --> H
    E -->|Yes| I[履歴の整合性を確認]
    E -->|No| J[ブランチ名の確認]
    I --> K[force push が必要か判断]
    J --> L[正しいリモートか確認]
  

よくある原因

  • リモートに他の人がpushした — チーム開発で最も多い原因
  • 別端末で先にpushした — 同じ作業を複数環境で行っている場合
  • git commit –amend を使った — 既にpush済みのコミットを修正した
  • git rebase を使った — push済みのブランチをリベースした
  • git reset を使った — push済みの履歴を巻き戻した
  • ブランチ名が違う — ローカルとリモートで異なるブランチを指定している
  • フォークしたリポジトリを操作している — upstreamとoriginを混同している

操作手順

ステップ1: 現在の状態を確認する

    git status
git log --oneline -5
  

🔍 チェックポイント: 自分がどのブランチにいるか、最新のコミットが何かを確認

ステップ2: リモートの最新情報を取得する

    git fetch origin
  

🔍 チェックポイント: エラーなく完了すること

ステップ3: ローカルとリモートの差分を確認する

    # リモートにあってローカルにないコミット
git log HEAD..origin/main --oneline

# ローカルにあってリモートにないコミット
git log origin/main..HEAD --oneline
  

🔍 チェックポイント: 両方に差分がある場合は「分岐」している状態

ステップ4-A: リモートの変更を取り込む(通常のケース)

    git pull --rebase origin main
  

🔍 チェックポイント: Successfully rebased and updated と表示されれば成功

コンフリクトが発生した場合:

    # コンフリクトを解消してから
git add <ファイル名>
git rebase --continue
  

ステップ4-B: マージで取り込む場合

    git pull origin main
  

🔍 チェックポイント: マージコミットが作成される。履歴を直線的に保ちたい場合は --rebase を使う

ステップ5: 再度pushする

    git push origin main
  

🔍 チェックポイント: エラーなく完了し、リモートに反映されること

NG行動(やってはいけないこと)

  • 安易に git push --force を使う — 他の人のコミットを消す可能性がある
  • 確認せずに git pull する — 意図しないマージコミットが作られることがある
  • エラーを無視して再度pushを繰り返す — 状況は変わらない
  • git reset --hard origin/main を安易に実行する — ローカルの作業が消える

⚠️ 警告: --force--force-with-lease は、自分だけが使っているブランチ以外では使用を避ける。チームで共有しているブランチでは、他のメンバーの作業を破壊する可能性がある。

よくある質問(FAQ)

Q1: --force--force-with-lease の違いは?

A: --force-with-lease は、自分が最後にfetchした時点からリモートが変わっていない場合のみ強制pushする。他の人のpushを上書きするリスクを軽減できる。ただし、完全な安全策ではない。

Q2: rebaseとmergeどちらを使うべき?

A: 履歴を直線的に保ちたい場合は rebase、マージした事実を残したい場合は merge。チームのルールに従う。迷う場合は merge が安全。

Q3: コンフリクトが複雑で解消できない場合は?

A: git rebase --abort でリベースを中止し、元の状態に戻せる。その後、git pull(マージ)を試すか、チームメンバーに相談する。

関連するトラブル

準備中

解決しない場合

  • 公式ドキュメント: Git - git-push Documentation
  • 確認すべきログ: git reflog で過去の操作履歴を確認
  • 次に調べるキーワード: 「git fetch vs pull」「git rebase conflict」「git force-with-lease」