「git pushがエラーで弾かれる…」「リベース後にpushできない」「間違ったコミットを修正したい」こんな時、git push --forceという”禁断のコマンド”が頭をよぎりますよね。
でも待ってください!強制プッシュは核兵器レベルで危険です。一瞬でチーム全体の作業を破壊し、数時間~数日分のコードを消し飛ばす可能性があります。
しかし、正しく理解して使えば、強制プッシュはGit運用における強力な味方になります。この記事では、強制プッシュの仕組みから、安全な--force-with-leaseの使い方、万が一の復旧方法まで、すべてを徹底解説します。
- 強制プッシュとは?なぜ必要なのか
- git push –force の危険性
- 安全な強制プッシュ:–force-with-lease
- 強制プッシュの実践的な使い方
- 共有ブランチで強制プッシュする場合の手順
- 強制プッシュの取り消し・復旧方法
- ブランチ保護設定
- よくあるトラブルシューティング
- ベストプラクティスとエイリアス設定
- よくある質問(FAQ)
- Q1:–force と -f は同じですか?
- Q2:強制pushすると履歴は完全に消えますか?
- Q3:チーム開発で強制pushは絶対NGですか?
- Q4:–force-with-leaseは100%安全ですか?
- Q5:間違って強制pushした場合、何分以内なら復旧できますか?
- Q6:プルリクエストを修正するとき、毎回強制pushが必要ですか?
- Q7:強制pushの権限を特定の人だけに制限できますか?
- Q8:一人で開発している場合、–forceと–force-with-leaseどちらを使うべきですか?
- Q9:CIが走っている最中に強制pushするとどうなりますか?
- Q10:強制pushを完全に禁止する方法はありますか?
- まとめ:強制プッシュの鉄則
強制プッシュとは?なぜ必要なのか

通常のgit pushが失敗する理由
まず、なぜpushがエラーになるのかを理解しましょう。
通常のpush:
$ git push origin main
エラー例:
To https://github.com/user/repo.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'https://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.
このエラーの意味:
ローカル: A ← B ← C ← D
↑ あなたのHEAD
リモート: A ← B ← C ← E ← F
↑ リモートのHEAD
リモートにはEとFという新しいコミットがあるのに、あなたのローカルはDを追加しようとしている。履歴が分岐しているため、Gitは安全のためpushを拒否します。
強制プッシュの動作
強制プッシュは、この安全装置を無視して上書きします。
git push --force origin main
結果:
ローカル: A ← B ← C ← D
↑ あなたのHEAD
リモート: A ← B ← C ← D (E と F は消滅!)
↑ 強制的に上書き
リモートのEとFは完全に消え去ります。もし他の人がEとFを基に作業していたら…悲劇が起こります。
強制プッシュが必要になる典型的なシーン
1. git rebase 後
# リベースで履歴を書き換えた
git rebase -i HEAD~3
# pushしようとするとエラー
git push origin feature/new-design
# → rejected!
# 強制プッシュが必要
git push --force origin feature/new-design
2. コミット履歴の修正後
# 直前のコミットを修正
git commit --amend -m "Fix typo in commit message"
# pushが拒否される
git push origin main
# → rejected!
# 強制プッシュが必要
git push --force origin main
3. コミットの取り消し後
# 間違ったコミットをリセット
git reset --hard HEAD~1
# pushが拒否される
git push origin main
# → rejected!
# 強制プッシュが必要
git push --force origin main
4. リモートの間違いを修正
# 誤ってpushした機密情報を削除
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch secrets.txt' HEAD
# 強制プッシュして反映
git push --force origin main
git push –force の危険性
危険度レベル:★★★★★(最高)
なぜ危険なのか?
| リスク | 説明 | 影響範囲 |
|---|---|---|
| コミットの消失 | リモートのコミットが完全に消える | チーム全員 |
| 作業の喪失 | 他の人の作業が上書きされる | チーム全員 |
| 同期エラー | 他のメンバーがpull/pushできなくなる | チーム全員 |
| マージ地獄 | 修復にコンフリクト解決が必要 | チーム全員 |
| 信頼の喪失 | チームメンバーからの信頼を失う | あなた |
実際の被害例
ケース1:チームメンバーAさんの悲劇
【時系列】
10:00 - Aさんが新機能をコミット&push(コミットE, F)
11:00 - あなたがリベースして強制push(E, Fが消滅)
11:30 - Aさんがpushしようとする→エラー
12:00 - Aさんが無理やりpull→自分の変更が消える
12:30 - 「2時間の作業が消えたんですけど…」
ケース2:本番環境への誤爆
【時系列】
14:00 - mainブランチで開発していた(つもりがmainだった)
15:00 - リベースして整理
15:30 - git push --force origin main(本番ブランチに強制push)
15:31 - CIが走って本番デプロイ開始
15:32 - 本番環境が壊れる
15:33 - 「やってしまった…」
ケース3:履歴の完全消失
【被害】
- 3ヶ月分のコミット履歴が消える
- 重要な設計判断の記録が失われる
- 誰が何をしたか分からなくなる
- git blameが使えなくなる
- チーム全体で復旧に丸1日
安全な強制プッシュ:–force-with-lease
–force-with-lease とは?
--force-with-leaseは、安全装置付きの強制プッシュです。
通常の –force:
git push --force origin main
# → リモートの状態を無視して強制上書き
安全な –force-with-lease:
git push --force-with-lease origin main
# → リモートが想定通りなら上書き、
# そうでなければエラーで停止
–force-with-lease の仕組み
シナリオ1:安全な場合(成功)
【状況】
- あなたが最後にfetchした時点:リモートはコミットC
- 現在のリモート:コミットC(変化なし)
- あなたのローカル:コミットDを追加
【実行】
$ git push --force-with-lease origin main
✅ 成功! リモートは D に更新される
シナリオ2:危険な場合(失敗)
【状況】
- あなたが最後にfetchした時点:リモートはコミットC
- 現在のリモート:コミットE(誰かがpushした!)
- あなたのローカル:コミットDを追加
【実行】
$ git push --force-with-lease origin main
❌ エラー!
error: failed to push some refs to 'origin'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.
–force と –force-with-lease の比較表
| 項目 | --force | --force-with-lease |
|---|---|---|
| 安全性 | ❌ 最低 | ✅ 高い |
| 他人の変更 | 無視して上書き | チェックしてから上書き |
| 使用場面 | 一人開発のみ | チーム開発でも可 |
| 推奨度 | ❌ 非推奨 | ✅ 推奨 |
| エイリアス | -f | なし |
–force-with-lease の注意点
⚠️ 罠:fetch直後は意味がない
# これは危険!
git fetch origin main
git push --force-with-lease origin main
なぜ?
fetchで最新状態を取得--force-with-leaseは「最後にfetchした時点」をチェック- つまり、fetchした直後なら常に成功してしまう
正しい使い方:
# fetch せずに確認
git push --force-with-lease origin main
# エラーが出たら内容を確認
git fetch origin main
git log origin/main..HEAD # 何が違うか確認
git log HEAD..origin/main # リモートの新しいコミット確認
# 問題なければ再度実行
git push --force-with-lease origin main
強制プッシュの実践的な使い方
パターン1:個人ブランチでのリベース
# 自分専用のfeatureブランチ
git checkout feature/my-work
# コミット履歴を整理
git rebase -i HEAD~5
# 競合があれば解決
git rebase --continue
# 安全に強制push
git push --force-with-lease origin feature/my-work
ポイント:
- ✅ 自分だけが使うブランチなら安全
- ✅
--force-with-leaseで念のため確認 - ✅ チームに事前通知不要
パターン2:プルリクエスト修正後
# プルリク用ブランチで作業
git checkout feature/new-api
# レビュー指摘でコミットを修正
git rebase -i origin/main
# または直前のコミットを修正
git commit --amend
# 強制pushで反映
git push --force-with-lease origin feature/new-api
ポイント:
- ✅ プルリク中のブランチは自分専用
- ✅ GitHub/GitLabのプルリクは自動更新される
- ⚠️ レビュワーに通知(コミットハッシュが変わる)
パターン3:機密情報の削除
# 機密ファイルをコミット履歴から完全削除
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch config/secrets.yml' \
--prune-empty --tag-name-filter cat -- --all
# 強制pushで反映
git push --force --all origin
git push --force --tags origin
ポイント:
- ⚠️ チーム全員に事前通知必須
- ⚠️ 全員が再cloneまたはリセット必要
- ⚠️ 作業が止まる時間を作る
パターン4:間違ったコミットの修正
# 間違ったコミットをリセット
git reset --hard HEAD~3
# 正しい内容で再コミット
git add .
git commit -m "Correct implementation"
# 強制push
git push --force-with-lease origin feature/fix-bug
ポイント:
- ✅ 自分専用ブランチなら問題なし
- ⚠️ 共有ブランチなら絶対NG
共有ブランチで強制プッシュする場合の手順

どうしてもmainやdevelopに強制pushしなければならない場合の手順です。
事前準備チェックリスト
□ 本当に強制pushが必要か?(revertで対応できないか?)
□ チーム全員に連絡したか?
□ 作業中のメンバーがいないか確認したか?
□ バックアップを取ったか?
□ 影響範囲を把握したか?
□ リカバリー手順を準備したか?
□ 上司・チームリーダーの承認を得たか?
ステップ1:チーム全員に通知
【緊急】mainブランチへ強制push予定
実施日時:2025年12月12日 14:00
対象ブランチ:main
理由:機密情報の削除
影響:コミット abc123 以降の履歴が変更されます
【全員にお願い】
1. 13:50までに作業中の変更をpush
2. 14:00-14:30は作業を一時停止
3. 14:30以降に下記コマンドで同期
# 同期コマンド
git checkout main
git fetch origin
git reset --hard origin/main
ステップ2:バックアップ作成
# ブランチを別名で保存
git branch backup-main-20251212 main
git push origin backup-main-20251212
# またはローカルにバンドル保存
git bundle create main-backup-20251212.bundle main
ステップ3:強制push実行
# 最終確認
git log origin/main..HEAD # pushされる内容
git log HEAD..origin/main # 消える内容
# 実行
git push --force-with-lease origin main
# 確認
git log origin/main
ステップ4:チーム全員へ同期手順を案内
# メンバーが実行するコマンド
git checkout main
git fetch origin
# 作業中の変更がある場合
git stash save "Before force push sync"
# リモートに強制同期
git reset --hard origin/main
# 作業を戻す
git stash pop
強制プッシュの取り消し・復旧方法
方法1:reflogで復旧(最も確実)
リモートの履歴を確認:
git reflog show origin/main
出力例:
abc1234 origin/main@{0}: forced push
def5678 origin/main@{1}: push
789abcd origin/main@{2}: push
復旧:
# 1つ前の状態に戻す
git reset --hard origin/main@{1}
# 強制pushで反映
git push --force origin main
ポイント:
reflogは過去90日間保存される@{1}は「1つ前の状態」@{2}なら「2つ前の状態」
方法2:コミットハッシュで復旧
消えたコミットのハッシュを知っている場合:
# 消えたコミットに戻す
git reset --hard abc1234
# 強制pushで反映
git push --force origin main
方法3:他のメンバーから復旧
誰かがまだ古い状態を持っている場合:
# メンバーのローカルからpush
# (メンバー側で実行)
git push --force origin main
方法4:GitHubの保護機能で復元
GitHub:
1. Settings → Branches
2. main ブランチの "Edit" をクリック
3. "View history" から過去の状態を確認
4. 必要に応じて復元
GitLab:
1. Repository → Protected branches
2. Protected branches の履歴から復元
ブランチ保護設定
GitHub でブランチを保護する
1. リポジトリの Settings をクリック
2. Branches → Branch protection rules
3. "Add rule" をクリック
4. Branch name pattern: main (または develop)
5. 以下をチェック:
☑ Require a pull request before merging
☑ Require approvals (最低1人)
☐ Allow force pushes(絶対にチェックしない!)
☐ Allow deletions
6. "Create" をクリック
効果:
$ git push --force origin main
remote: error: GH006: Protected branch update failed for refs/heads/main.
強制pushが完全にブロックされます!
GitLab でブランチを保護する
1. Settings → Repository → Protected branches
2. Branch: main を選択
3. Allowed to merge: Maintainers
4. Allowed to push: No one
5. Allowed to force push: OFF (重要!)
6. "Protect" をクリック
Bitbucket でブランチを保護する
1. Repository settings → Branch permissions
2. "Add a branch permission"
3. Branch: main
4. Prevent deletion: ON
5. Prevent rewriting history: ON (これが強制push防止)
6. "Save" をクリック
よくあるトラブルシューティング
トラブル1:「protected branch」エラー
症状:
$ git push --force origin main
remote: error: GH006: Protected branch update failed for refs/heads/main.
原因: ブランチが保護されている
解決方法:
パターンA:保護を一時解除(管理者のみ)
1. GitHub Settings → Branches
2. mainの保護ルールを削除
3. 強制push実行
4. 保護ルールを再設定
パターンB:revertを使う(推奨)
# 強制pushの代わりにrevert
git revert abc1234
git push origin main
トラブル2:「non-fast-forward」エラー
症状:
$ git push --force-with-lease origin main
error: failed to push some refs
hint: Updates were rejected because the remote contains work
原因: 誰かがリモートにpushした
解決方法:
# ステップ1:リモートの変更を確認
git fetch origin main
git log HEAD..origin/main
# ステップ2:内容を確認
git diff HEAD origin/main
# ステップ3A:マージする
git merge origin/main
git push origin main
# ステップ3B:リベースする
git rebase origin/main
git push --force-with-lease origin main
# ステップ3C:本当に上書きする
git push --force origin main # 慎重に!
トラブル3:「Everything up-to-date」
症状:
$ git push --force origin main
Everything up-to-date
原因: ローカルとリモートが同じ状態
解決方法:
# 現在の状態を確認
git log origin/main..HEAD # ローカルの新しいコミット
git log HEAD..origin/main # リモートの新しいコミット
# 両方空なら本当に同じ
# どちらかに出力があれば確認
トラブル4:強制push後にチームメンバーがpushできない
メンバー側の症状:
$ git push origin main
error: failed to push some refs
hint: Updates were rejected
解決手順(メンバー側):
# ステップ1:現在の作業を退避
git stash save "Before sync with forced push"
# ステップ2:リモートの最新を取得
git fetch origin
# ステップ3:強制的にリモートに合わせる
git reset --hard origin/main
# ステップ4:退避した作業を戻す
git stash pop
# ステップ5:コンフリクトがあれば解決
# (手動で解決)
# ステップ6:再度コミット&push
git add .
git commit -m "Resolve conflicts after force push"
git push origin main
トラブル5:間違って本番ブランチに強制pushした
即座に実行:
# ステップ1:reflogで直前の状態を確認
git reflog show origin/main
# ステップ2:1つ前に戻す
git reset --hard origin/main@{1}
# ステップ3:すぐに強制pushで復元
git push --force origin main
# ステップ4:チームに通知
# (Slackなどで即座に報告)
時間が経ってしまった場合:
# バックアップブランチがあれば
git checkout backup-main-20251212
git checkout -b main-restore
git push --force origin main
ベストプラクティスとエイリアス設定
推奨エイリアス
# 安全な強制push
git config --global alias.pushf 'push --force-with-lease'
# 使い方
git pushf origin main
より高度なエイリアス:
# 確認付き強制push
git config --global alias.fpush '!git push --force-with-lease "$@" || (echo "Push failed. Check remote changes with: git fetch && git log HEAD..@{u}" && false) #'
# 使い方
git fpush origin main
.gitconfig 設定例
[alias]
# 安全な強制push
pushf = push --force-with-lease
# 強制pushの影響確認
push-dry = push --force-with-lease --dry-run
# リモートとの差分確認
push-check = !git fetch && git log HEAD..@{u} --oneline
# 安全装置:常に--force-with-leaseを使う
push-force = push --force-with-lease
# デフォルトの動作 default = current # 強制pushを警告 followTags = true
チーム開発のルール例
ルール1:個人ブランチのみOK
✅ 許可:feature/your-name/*
✅ 許可:fix/issue-123
❌ 禁止:main, develop, release/*
ルール2:事前通知必須
強制pushする場合:
1. Slackで事前通知(30分前)
2. 理由を明記
3. 影響範囲を説明
4. 同期手順を共有
ルール3:–forceは禁止
✅ 使用OK:git push --force-with-lease
❌ 使用NG:git push --force
❌ 使用NG:git push -f
よくある質問(FAQ)
Q1:–force と -f は同じですか?
A:はい、完全に同じです。
# これらはすべて同じ意味
git push --force origin main
git push -f origin main
ただし、--force-with-leaseには短縮形がありません。
Q2:強制pushすると履歴は完全に消えますか?
A:リモートからは消えますが、復旧可能です。
- reflog:90日間は保存される
- 他のメンバーのローカル:まだ残っている
- GitHub/GitLab:保護機能で復元可能(設定次第)
Q3:チーム開発で強制pushは絶対NGですか?
A:状況によります。
| ブランチ | 強制push |
|---|---|
| main, master | ❌ 原則禁止 |
| develop | ❌ 原則禁止 |
| release/* | ❌ 禁止 |
| hotfix/* | △ 要相談 |
| feature/個人名 | ✅ OK |
| プルリク用ブランチ | ✅ OK |
Q4:–force-with-leaseは100%安全ですか?
A:いいえ、以下の場合は無効です。
罠1:fetch直後
git fetch origin
git push --force-with-lease origin main
# ↑ 常に成功してしまう
罠2:自動fetchの設定
# .gitconfigに以下がある場合
fetch = +refs/heads/*:refs/remotes/origin/* # バックグラウンドでfetchされて無効化
罠3:他人が同時作業
10:00 - あなたがfetch
10:30 - Aさんがpush
10:31 - あなたが--force-with-lease
(Aさんの変更を上書き!)
Q5:間違って強制pushした場合、何分以内なら復旧できますか?
A:即座に対処すれば、ほぼ100%復旧可能です。
| 経過時間 | 復旧の可能性 |
|---|---|
| 1分以内 | 99% (reflogで即復旧) |
| 1時間以内 | 95% (メンバーがまだ持っている) |
| 1日以内 | 70% (バックアップ・保護機能) |
| 1週間以内 | 30% (運次第) |
| 1ヶ月以上 | 10% (ほぼ不可能) |
重要: 気づいたら即座にチームに連絡してください。
Q6:プルリクエストを修正するとき、毎回強制pushが必要ですか?
A:はい、コミット履歴を書き換える場合は必要です。
# プルリク後にコミットを修正
git commit --amend
# または
git rebase -i HEAD~3
# 強制pushで反映
git push --force-with-lease origin feature/my-pr
これは正常な使い方です。プルリク用ブランチは自分専用なので安全です。
Q7:強制pushの権限を特定の人だけに制限できますか?
A:はい、可能です。
GitHub:
Settings → Branches → Branch protection rules
☑ Restrict who can push to matching branches
→ 特定のユーザー・チームを選択
GitLab:
Settings → Repository → Protected branches
Allowed to force push: Select users/roles
Bitbucket:
Repository settings → Branch permissions
Prevent rewriting history: Exceptions (特定ユーザー)
Q8:一人で開発している場合、–forceと–force-with-leaseどちらを使うべきですか?
A:–force-with-leaseを使いましょう。
理由:
- 習慣づけが大切(チーム開発に移行した時のため)
- 自分でも複数デバイスから作業する可能性
- うっかりミスを防げる
ただし、完全に一人で、ミスしても問題ない場合は--forceでもOKです。
Q9:CIが走っている最中に強制pushするとどうなりますか?
A:CIが失敗するか、古いコードでビルドされます。
ベストプラクティス:
1. CIが完了するまで待つ
2. または、CIを手動でキャンセル
3. 強制push実行
4. CIが再実行される
Q10:強制pushを完全に禁止する方法はありますか?
A:サーバー側フック(pre-receive)で実装できます。
GitHub Actions例:
name: Prevent Force Push
on:
push:
branches: [main, develop]
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Check force push
run: |
if git log --format=%B -n 1 $GITHUB_SHA | grep -q "force-push"; then
echo "Force push detected!"
exit 1
fi
GitLab CI例:
prevent-force-push:
script:
- git reflog show origin/main | grep -q "forced"
- if [ $? -eq 0 ]; then exit 1; fi
only:
- main
まとめ:強制プッシュの鉄則
使っていい場面
✅ 自分専用のfeatureブランチ
- 例:
feature/your-name/new-feature - 誰にも迷惑をかけない
✅ プルリクエスト用ブランチ
- コミット履歴の整理
- レビュー指摘の修正後
✅ 実験用・一時ブランチ
experiment/*temp/*
絶対に使ってはいけない場面
❌ mainブランチ
- チーム全員に影響
- 本番環境に直結
❌ developブランチ
- 開発全体の基準
- 全員が使う
❌ 他人が作業中のブランチ
- 相手の作業を破壊
- 取り返しがつかない
黄金ルール
--forceは使わない、--force-with-leaseを使う- 共有ブランチでは絶対にしない
- 事前にチームに連絡する
- バックアップを必ず取る
- 迷ったらrevertを使う
最重要ポイント:
強制プッシュは最後の手段です。
- まず
git revertを検討 - 次に
git mergeを検討 - それでもダメなら
git push --force-with-lease
そして、迷ったら誰かに相談してください。
5分の相談で、数時間の復旧作業を避けられます。
この記事を読んだあなたは、もう安全に強制プッシュを使いこなせるはずです。ただし、使わないで済むなら、それが一番です!


コメント