git push が rejected になる原因と解決方法|non-fast-forward・branch protection・LFS対応

  • 作成日 2026.06.25
  • git
git push が rejected になる原因と解決方法|non-fast-forward・branch protection・LFS対応

Git でリモートにプッシュしようとした時に頻発するエラー:

$ git push origin main
To github.com:user/repo.git
 ! [rejected]        main -> main (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.

または:

 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'github.com:user/repo.git'

git push は Git 操作の最後の関門。せっかく書いたコードがリモートに送れない状況は本当にストレスです。

しかも、

  • なぜ rejected されるのか分からない
  • git pull してまた push、を繰り返してマージコミットが大量発生
  • --force でいいの? --force-with-lease との違いは?
  • commit --amend した後の push が通らない
  • rebase 後の push が通らない
  • branch protection で force push できない
  • 100MB のファイルが原因?
  • 初回 push でいきなり rejected

など、状況によって対処が分かれます。

本記事では、git push で発生する rejected エラーのすべての原因と解決方法を、現場で即使えるトラブルシューティングとして整理します。エラーの本質、pull --rebase vs merge--force-with-lease vs --force、amend/rebase 対応、branch protection、Git LFS、初回プッシュ、pre-receive hook、ベストプラクティス、FAQまで完全網羅。この1本で push 関連のトラブルに自信を持って対処できます。


目次

結論:今すぐ試すべき3ステップ

時間がない方向けに、最短の対処手順を示します。

ステップ1:状況確認

# リモートの最新状態を取得(push せず)
git fetch origin

# 現在の状況確認
git status
git log --oneline -5
git log --oneline origin/main -5

# 差分確認
git log HEAD..origin/main --oneline   # リモートにあって自分にないコミット
git log origin/main..HEAD --oneline   # 自分にあってリモートにないコミット

ステップ2:標準的な解決

# パターンA: リモートの変更を取り込む(推奨)
git pull --rebase origin main
git push origin main

# パターンB: マージで取り込む
git pull origin main
git push origin main

ステップ3:force push が必要なケース

# 自分の feature ブランチで rebase / amend した
git push --force-with-lease origin feature

# ⚠️ 共有ブランチでは絶対NG

詳細は以下で解説します。


まず押さえる:rejected エラーの本質

Git のプッシュルール

Git は 「リモートのコミット履歴を上書きしない」 ことを基本ルールとします。リモートに自分が知らないコミットがある場合、プッシュは拒否されます。

fast-forward とは

リモート: A → B → C
ローカル: A → B → C → D → E

git push  → OK(remote が ローカルの祖先)
remote が A → B → C → D → E に「早送り」

non-fast-forward(rejected の理由)

リモート: A → B → C → F   ← 誰かがF追加
ローカル: A → B → C → D → E ← 自分はD, E追加

git push  → 拒否
リモートの F がローカルに存在しないため、上書きすると F が消える

これが non-fast-forward エラー。Git は データロスを防ぐためにプッシュを拒否。

エラーメッセージの種類

メッセージ原因
(non-fast-forward)リモートが先行
(fetch first)リモートに新規コミット
(needs force)ローカルが履歴改変済み
(stale info)force-with-lease で remote が変更されている
Cannot force-push to this protected branchブランチ保護
file is X MB, exceeds the maximum file size巨大ファイル
pre-receive hook declinedリモート側hook で拒否

それぞれ対処が異なります。


【原因①】リモートが先行している(最頻出)

最も多いケース。他の開発者がプッシュしたか、Web UI でコミットがあった。

確認

git fetch origin
git log HEAD..origin/main --oneline
# a1b2c3d Fix bug in login
# e4f5g6h Update dependencies

リモートに自分が持っていないコミットがある。

解決A:merge で取り込む(標準的)

git pull origin main
# = git fetch + git merge

git push origin main

メリット:

  • シンプル
  • 履歴がそのまま残る

デメリット:

  • マージコミットが増える
  • 履歴が複雑になる

解決B:rebase で取り込む(推奨)

git pull --rebase origin main
# = git fetch + git rebase

git push origin main

メリット:

  • マージコミットなし
  • 履歴が線形でクリーン

デメリット:

  • 自分のコミットハッシュが変わる
  • コンフリクト解消を各コミットごとに行う場合がある

merge vs rebase

観点mergerebase
履歴複雑(マージコミット)線形
コンフリクト1回コミット毎
コミットハッシュ維持変わる
共有ブランチ安全注意(既プッシュ後は危険)
推奨共有ブランチフィーチャーブランチ

デフォルト設定

# Git 2.27+ で警告される
hint: Pulling without specifying how to reconcile divergent branches is
hint: discouraged.

対処(推奨):

# 全体設定(rebase デフォルト)
git config --global pull.rebase true

# またはローカル設定
git config pull.rebase true

これで git pullgit pull --rebase と同じ動作に。


【原因②】git commit –amend 後のpush

直前のコミットを修正(amend)した場合:

# プッシュ済みコミットを amend
git commit --amend -m "Better commit message"

git push origin feature
# rejected: non-fast-forward

なぜrejected?

amend は新しいコミット(別ハッシュ)を作成。元のコミットを置き換えるため、リモートと履歴が乖離します。

解決

ブランチが自分専用なら force push:

git push --force-with-lease origin feature

他人と共有しているブランチでは絶対 NG。事前に通知 & 合意を。

推奨:amend 前の確認

# プッシュ済みかチェック
git log origin/feature..HEAD
# 何も出なければプッシュ済み

# まだプッシュしてない場合のみ amend が安全

【原因③】git rebase 後のpush

リベース後は全コミットのハッシュが変わるため、リモートと完全に履歴乖離:

git checkout feature
git rebase main
# 全コミットのハッシュ変更

git push origin feature
# rejected

解決

# 自分の feature ブランチで rebase した場合
git push --force-with-lease origin feature

公開済みブランチでは rebase 禁止

# ❌ main / develop など共有ブランチで rebase
git checkout main
git rebase feature
git push --force-with-lease origin main
# 他の開発者のローカル history と整合性崩壊

共有ブランチには merge を使う。


–force-with-lease vs –force

–force(強制上書き、危険)

git push --force origin feature

リモートの状態を問答無用で上書き。他人のコミットも消える。

–force-with-lease(安全版、推奨)

git push --force-with-lease origin feature

最後にfetchした時のリモート状態から変わっていなければプッシュ。誰かが新しくpush していたら拒否(自分のローカルでは見えない変更を保護)。

比較

観点–force–force-with-lease
チェックなしリモート状態確認
他人のコミット保護
安全性危険安全
推奨度ほぼ非推奨標準的なforce push

alias で安全に

# git pushf で --force-with-lease を実行
git config --global alias.pushf 'push --force-with-lease'

# 利用
git pushf origin feature

これで誤って --force を打たない仕組みに。


【原因④】初回プッシュで rejected

新規リポジトリの初回プッシュで:

git init
git add .
git commit -m "Initial commit"
git remote add origin git@github.com:user/repo.git
git push -u origin main
# rejected: failed to push some refs

なぜ?

GitHub/GitLab でREADME/LICENSE/.gitignore を自動生成したリポジトリは、既に1コミットあります。ローカルとリモートに共通の祖先がない状態。

解決A:リモートの内容を取り込む

git pull origin main --allow-unrelated-histories
# 「無関係な履歴」も許可してmerge
git push -u origin main

解決B:ローカルで上書き(リモートのREADME等を捨てる)

git push --force origin main

リモートの README / LICENSE が必要なら事前に手動コピー

推奨:リモートを空で作る

GitHub でリポジトリ作成時に 「Initialize this repository with」のチェックを全て外す。これで初回プッシュがスムーズに。


【原因⑤】Branch Protection(GitHub/GitLab)

remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: Cannot force-push to this protected branch

main / develop などのブランチが保護されている。

確認

GitHub: Settings → Branches → Branch protection rules

GitLab: Settings → Repository → Protected branches

対応A:プルリクエスト経由

# 別ブランチを作って PR
git checkout -b fix/my-changes
git push origin fix/my-changes
# GitHub/GitLab で PR 作成、Web で merge

これが推奨フロー。直接 push せず、PR/MR を通す。

対応B:保護の一時解除(管理者のみ)

GitHub の場合:

  • Settings → Branches → 該当ルール編集
  • “Allow force pushes” を一時的に有効化
  • 作業後、必ず元に戻す

対応C:管理者に依頼

直接 push が必要なら、リポジトリ管理者にコンタクト。


【原因⑥】大きすぎるファイル

remote: error: GH001: Large files detected. You may want to try Git Large File Storage
remote: error: Trace: ...
remote: error: See https://gh.io/lfs for more information.
remote: error: File large_data.csv is 150.00 MB; this exceeds GitHub's file size limit of 100.00 MB

GitHub は1ファイル 100MB、リポジトリ合計1GB 推奨

解決A:ファイルを削除

# 削除してコミット履歴からも除外
git rm --cached large_data.csv
echo "large_data.csv" >> .gitignore
git add .gitignore
git commit -m "Remove large file"
git push origin main

ただし過去のコミットにあると消えない。

解決B:履歴からファイル削除(破壊的)

# 全履歴から large_data.csv を削除
git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch large_data.csv" \
  --prune-empty --tag-name-filter cat -- --all

git push --force-with-lease origin --all

または git-filter-repo(推奨):

# インストール
pip install git-filter-repo

git filter-repo --path large_data.csv --invert-paths
git push --force-with-lease origin --all

解決C:Git LFS

# Git LFS インストール
sudo apt install git-lfs
git lfs install

# 大きいファイルを LFS で管理
git lfs track "*.csv"
git lfs track "*.zip"
git add .gitattributes
git commit -m "Track large files with LFS"

# 通常通り push
git add large_data.csv
git commit -m "Add data"
git push origin main

LFS は別の保管場所に大ファイルを保存し、Git リポジトリには参照のみ。

詳細はDocker no space left on device の記事(容量管理)も参照。


【原因⑦】pre-receive hook で拒否

remote: error: pre-receive hook declined

サーバー側の pre-receive フックがプッシュを拒否。

原因例

  • コミットメッセージ規約違反
  • ファイル名規約違反
  • テスト失敗
  • 秘密鍵・APIキー混入検知
  • 巨大ファイル検知

解決

エラーメッセージをよく読む:

remote: ERROR: commit message must start with [JIRA-]
remote: error: pre-receive hook declined

→ コミットメッセージ修正:

git commit --amend -m "[JIRA-123] Fix bug"
git push origin feature

秘密情報の混入

remote: error: GH013: Repository rule violations found
remote: - A secret was detected

→ 該当ファイルから秘密情報を削除し、ローテーション:

# .env をうっかりコミット
git rm --cached .env
echo ".env" >> .gitignore
git add .gitignore
git commit --amend

# 秘密情報は必ずローテーション(無効化+新規発行)

【原因⑧】間違ったブランチを指定

git push origin
# rejected: ???

確認

git status
# On branch feature
# Your branch is up to date with 'origin/feature'.

# 自分が今どのブランチか
git branch --show-current

# upstream の設定
git branch -vv

修正

# 明示的に指定
git push origin feature

# upstream 設定
git push -u origin feature

または push.default 設定:

git config --global push.default simple
# 現在のブランチを同名で push(デフォルト)

解決パターン早見表

状況解決コマンド
リモートが先行(通常)git pull --rebase origin BRANCH && git push
マージで取り込みたいgit pull origin BRANCH && git push
amend した自分のブランチgit push --force-with-lease origin BRANCH
rebase した自分のブランチgit push --force-with-lease origin BRANCH
初回プッシュ(リモートに既存)git pull --allow-unrelated-histories origin main
ブランチ保護Pull Request 経由でmerge
大きいファイルGit LFS or 履歴から削除
共有ブランチで間違えた手動 revert(force push 禁止)
意図せず amend したreflog から復元、force push

reflog による救済

force push で他人のコミットを上書きしてしまったら…

自分のローカルから復元

# reflog でこれまでの HEAD 履歴
git reflog
# d4e5f6g HEAD@{0}: push: ...
# a1b2c3d HEAD@{1}: commit: My work
# 7890abc HEAD@{2}: pull: ...    ← 復元したい

# その時点に戻る
git reset --hard 7890abc

# 元の状態をpush
git push --force-with-lease origin main

他人のローカルから復元

# 他のメンバーのローカルに上書きされる前の commit があれば取得
git fetch origin
git reset --hard origin/main

または GitHub の Events / Activity から復元可能なケースも。

⚠️ 完全に消えるとリカバリ不能。force push は慎重に。


CI/CD での push rejected

GitHub Actions / GitLab CI で自動 commit/push する時に発生:

競合状態

# .github/workflows/auto-commit.yml
- name: Commit changes
  run: |
    git add -A
    git commit -m "Auto update"
    git push   # ← 他のCIと同時実行で rejected

解決:pull –rebase 後 push

- name: Commit and push
  run: |
    git pull --rebase
    git add -A
    git commit -m "Auto update" || echo "No changes"
    git push
  
  # またはリトライ
- name: Push with retry
  run: |
    for i in 1 2 3; do
      git pull --rebase && git push && break
      sleep 5
    done

rake task 作り方の記事crontab 書き方 例の記事も自動化の参考に。


安全なワークフロー

1. 共有ブランチでは絶対にforce push しない

# ❌ 絶対NG
git push --force origin main
git push --force-with-lease origin develop

main / develop / 共有ブランチでは通常の push のみ

2. feature ブランチでは –force-with-lease

# ✅ 自分のfeature ブランチなら OK
git push --force-with-lease origin feature/my-work

3. PR 経由のマージ

feature/my-work(force push可)
       ↓ Pull Request
main(force push禁止)

4. rebase の前に必ず pull

git checkout feature
git pull --rebase origin main
git push --force-with-lease origin feature

5. 定期的に rebase でクリーンに

# 朝に1回
git fetch origin
git rebase origin/main

長期間放置するとマージが大変に。

6. コミット粒度を細かく

# ❌ 1日溜めて一気にpush
# 100ファイル変更、1コミット

# ✅ こまめにcommit & push
git commit -m "Add feature skeleton"
git push
# 続けて作業
git commit -m "Implement logic"
git push

頻繁にpushすれば乖離が小さい。

7. リモートを fetch する習慣

# 作業開始前
git fetch origin

# pull は変更が確実な時だけ

fetch は副作用なし。pull は merge/rebase が発生。


トラブルシューティング

何度 pull しても rejected

ローカルとリモートで同じ問題を繰り返し起こしている可能性。

# 状態確認
git fetch origin
git status

# logで詳細
git log --graph --oneline --all -10

# 完全リセット(ローカルの変更を捨てる)
git fetch origin
git reset --hard origin/main
# ⚠️ ローカルの未push変更は失われる

Merge conflict が解消できない

# 状態確認
git status
# both modified: file.txt 等

# 該当ファイルを開いて手動編集
# <<<<<<< HEAD ... ======= ... >>>>>>> ブランチ名 マーカー削除

# 解消後
git add file.txt
git rebase --continue   # rebase中の場合
git commit              # merge中の場合

# rebase をやめたい
git rebase --abort

push が遅い・タイムアウト

# 大量のオブジェクト
git gc          # ガベージコレクション
git push origin BRANCH

# またはSSH 設定確認
# ~/.ssh/config
# Host github.com
#   ServerAliveInterval 60

詳細はSSH host key verification failed の記事も参照。

git push –force で誤って消した

# reflog から救済
git reflog show origin/main
# d4e5f6g refs/remotes/origin/main@{0}: update by push  
# a1b2c3d refs/remotes/origin/main@{1}: update by push  ← 戻したい

git push --force-with-lease origin a1b2c3d:main

ローカルにreflogが残っていれば復旧可能。

Permission denied (publickey)

これは別エラー。SSH鍵設定:

# 鍵の確認
ssh -T git@github.com

# 鍵生成
ssh-keygen -t ed25519 -C "your_email@example.com"

# 公開鍵を GitHub に登録
cat ~/.ssh/id_ed25519.pub

詳細はSSH host key verification failed の記事も参照。

Untracked working tree files would be overwritten by merge

# pull する前に未追跡ファイルが衝突
git status
# 該当ファイルを移動 or commit
mv conflicting_file conflicting_file.bak
git pull

よくある質問(FAQ)

Q1. pull –rebase と pull はどっちを使うべき?

状況推奨
feature ブランチで開発中pull --rebase
main/develop を更新pull(merge)
履歴を線形に保ちたいpull --rebase
マージコミットが許容されるpull

Git 2.27+ なら pull.rebase=true をデフォルトに設定推奨。

Q2. force push はいつしていい?

自分専用のブランチで rebase/amend した時のみ。共有ブランチでは絶対NG。

Q3. –force-with-lease で stale info エラー

! [rejected] feature -> feature (stale info)

→ リモートが最後にfetchした時から変わっている。

git fetch origin
# 確認後
git push --force-with-lease origin feature

Q4. 共有ブランチで間違えてforce push した

# 自分のローカルで戻す
git reset --hard d4e5f6g   # 元のcommit
git push --force-with-lease origin main

# できれば他のメンバーから完全な履歴をもらう

すぐにチームに連絡。

Q5. branch protection を一時解除する権限がない

→ リポジトリ管理者に依頼。または PR 経由でマージ。

Q6. 巨大ファイルを誤ってcommit してしまった

# pushしてないなら
git reset --soft HEAD~1
echo "large_file.bin" >> .gitignore
git add .gitignore
git commit -m "Add to gitignore"

# pushしてしまった場合
# git filter-repo で履歴から削除

Q7. push で改行コードエラー

warning: LF will be replaced by CRLF

Windows/Mac の混在。

# 自動変換の設定
git config core.autocrlf input   # Linux/Mac
git config core.autocrlf true    # Windows

Q8. リモートとローカルの差分確認

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

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

# 両方
git log --left-right HEAD...origin/main

詳細はLinuxでファイル差分を確認する方法の記事も参照。

Q9. push 前に確認するベストプラクティス

git fetch origin
git status
git diff origin/main..HEAD
git log --oneline origin/main..HEAD

push 前に何を送るかを確認する習慣。

Q10. GitHub Enterprise や GitLab Self-Hosted

エラーメッセージは同じだが、企業独自の pre-receive hook がある可能性。エラー詳細を管理者に確認。

Q11. main ブランチに直接 commit してしまった

# プッシュ前なら
git branch feature/my-work     # 新ブランチ作成
git reset --hard origin/main   # main を元に戻す
git checkout feature/my-work
git push -u origin feature/my-work
# PR作成

Q12. git pull で merge commit を増やしたくない

# 全体設定
git config --global pull.rebase true

# fast-forward only
git config --global pull.ff only
# fast-forward可能なpullしか許可しない

参考リンク・関連資料

Git 公式

関連ツール

関連記事(本サイト)


まとめ

git push rejected エラー、要点を再整理します。

エラータイプ早見表

メッセージ原因解決
non-fast-forwardリモートが先行pull --rebase または pull
fetch first同上同上
needs force履歴改変済みpush --force-with-lease
Protected branchbranch protectionPR経由
Large files100MB超Git LFS
pre-receive hookサーバhook拒否hook規約に従う

解決の流れ

# 1. 状況確認
git fetch origin
git log HEAD..origin/main --oneline

# 2. 取り込み(推奨)
git pull --rebase origin main

# 3. 解決後 push
git push origin main

force push の安全運用

# ❌ 危険:他人のコミット消す
git push --force

# ✅ 安全:リモート変更検知で拒否
git push --force-with-lease

# 自分専用ブランチでのみ使う

ベストプラクティス

  • 頻繁な pull: 朝・夕に rebase
  • 小さい単位でcommit/push: 乖離を最小化
  • 共有ブランチでforce push 禁止
  • PR経由のmerge: branch protection 設定
  • pull.rebase=true: 全体設定で履歴クリーン
  • alias pushf: force-with-lease をデフォルト
  • 大きいファイルはLFS

主なコマンド

git fetch origin                       # リモート情報取得
git pull --rebase origin main          # rebase で取り込み
git push --force-with-lease origin BR  # 安全な force push
git reflog                              # 操作履歴(救済)
git reset --hard origin/main           # リモートに合わせる

これらの知識は、Git を使ったあらゆる開発作業で活用できます。本記事をブックマークしておけば、push 関連のトラブルに自信を持って対処できるようになります。


本記事は2026年6月時点の情報をもとに、Git 2.40+ での動作確認・公式ドキュメント・GitHub/GitLab のドキュメントに基づき作成しています。Git のバージョンや使用するホスティングサービスによって挙動が異なる場合があるため、最新の情報はGit公式ドキュメントGitHub DocsGitLab Docs もあわせてご確認ください。