【Git】pushを取り消す方法|revert・force-with-lease・機密漏洩時の緊急対応まで完全ガイド

【Git】push を取り消す方法 Git

pushしてはじめて「やってしまった」と気づくミスは多いものです。機密情報をうっかり含めた、間違ったブランチに直pushした、テストが通っていないコミットをmainに流した、マージの方向を間違えた——どれもpush後だからこそ対応が難しい問題です。

この記事では、push後の取り消しに特化して実践的な対処法を解説します。共有後の履歴書き換えリスクを踏まえた判断基準、git revertによる安全な打ち消し、やむを得ない場合の--force-with-leaseの使い方、機密情報漏洩時の緊急対応、そしてチーム運用で気を付けるべき点までまとめます。コミット自体の取り消し方は【Git】コミットの取り消し方に詳しいので、本記事は「push後どう動くか」にフォーカスしています。

この記事で学べること

  • push後の取り消しで確認すべき4つの質問(保護ブランチ・共有範囲・機密性・単独作業)
  • 最推奨ルート:git revertで打ち消しコミットを追加する方法
  • 個人ブランチに限って使う--force-with-leaseの安全な使い方
  • 機密情報をpushしてしまったときの緊急対応(rotate→履歴書き換え)
  • 間違った共有ブランチに直接pushしたときのリカバリ手順
  • git push --forceで壊してしまったリモートをreflogで救う方法
  • チーム運用でpush取り消しの影響を最小化する作法
スポンサーリンク

まず確認:4つの質問で取り消し方が決まる

push後の取り消しは「履歴を書き換えるか」「打ち消しコミットで追記するか」の選択です。この選択を間違えると他メンバーのローカルを破壊したり、機密情報が履歴に残り続けるといった二次被害が発生します。以下の4つを必ず確認してから行動してください。

質問 Yesのとき Noのとき
保護ブランチ(main/develop等)か? 必ずrevert+PR force push検討可
他メンバーがpullした可能性がある? 必ずrevert force push検討可
機密情報が含まれる? rotate→履歴書き換え(filter-repo 通常の打ち消しでOK
自分だけが触る個人ブランチか? --force-with-lease 安全策でrevert

基本原則:「押したらもう戻せない」と考え、原則revertで打ち消しコミットを追加するのが最も安全です。git push --force--force-with-lease自分しか触っていない個人ブランチ限定の武器として使い分けましょう。

最推奨:git revert で push済みコミットを打ち消す

push後の取り消しは、原則としてgit revert打ち消しコミットを追加します。履歴を書き換えないため、他メンバーのローカルに影響を与えません。pushした瞬間に「やってしまった」と気づいたら、まずこれを検討してください。

単一コミットを打ち消す
# 取り消したいコミットのSHAを確認
git log --oneline -5

# 単一コミットを打ち消す(打ち消しコミットが追加される)
git revert <SHA>

# エディタでコミットメッセージ編集が開くので保存して閉じる
# 打ち消しコミットをpushして完了
git push origin <branch>

複数のpush済みコミットをまとめて打ち消す

直近N件をまとめて取り消すなら範囲指定が便利です。A^..B記法でAからBまでを逆順に打ち消します。

範囲指定で複数コミットを打ち消す
# 直近3件をまとめて打ち消す(新しいものから順に打ち消しコミット作成)
git revert HEAD~2..HEAD

# 中間コミットだけ打ち消したい場合
git revert a1b2c3d^..f4e5d6a

# 打ち消しコミットを個別に作らず、1つにまとめたい
git revert --no-commit HEAD~2..HEAD
git commit -m "revert: 直近3コミットの変更を一括で打ち消し"

# 最後にpush
git push origin <branch>

pushしてしまったマージコミットを打ち消す

マージコミットには親が2つあるため、-mで「どちらの親を基準に戻すか」を指定します。mainに機能ブランチをマージしてしまった場合、mainを基準(-m 1)にして打ち消すのが通例です。

マージコミットの打ち消し
# マージコミットのSHAを確認
git log --merges --oneline -5

# -m 1 で親1(マージ先ブランチ)を基準に打ち消し
git revert -m 1 <マージコミットSHA>

git push origin <branch>

ポイント:revert済みのコミットを後から再適用したい場合、単に再マージすると「打ち消しコミットがあるせいで取り込まれない」ことがあります。その場合は「打ち消しコミット自体をさらにrevertする」か、cherry-pickで個別にコミットを持ち込む必要があります。

revertの詳細(コンフリクト解消、--no-commitの使い方など)はコミットの取り消し方ガイドmergeコミットを取り消して履歴を元に戻す方法も参照してください。

個人ブランチ限定:–force-with-lease で安全に履歴を書き換える

自分しか触らない個人ブランチでpushしてしまった場合は、履歴を書き換えてpush --force-with-leaseする選択肢があります。「push前の状態に戻す」「コミットメッセージを修正する」「不要なコミットを削除する」ときに使います。

–force と –force-with-lease の違い

--forceは無条件でリモートを上書きしますが、--force-with-lease「リモートが自分の想定通りの状態なら上書き、違ったら拒否」という安全装置付きです。これにより、他メンバーが間に何かpushしていた場合の事故を防げます。

–force vs –force-with-lease
# 危険:他人のpushを知らずに上書きしてしまう可能性
git push --force origin feature/my-branch

# 安全:リモートが自分のローカルのorigin/xxxと一致していればpush、違えば拒否
git push --force-with-lease origin feature/my-branch

# さらに明示的に「この状態なら上書きOK」を指定(Git 2.30+)
git push --force-with-lease=feature/my-branch:<期待SHA> origin feature/my-branch

pushを巻き戻す典型例

個人ブランチでpushを巻き戻す
# push前に最新リモートを取得して判定を正確に
git fetch origin

# 1コミット前まで戻す(変更も完全破棄)
git reset --hard HEAD~1

# 安全チェック付きでpush
git push --force-with-lease origin feature/my-branch

# 「stale」エラーが出たらfetchし直してから再度試す
git fetch origin
git push --force-with-lease origin feature/my-branch

禁止事項:maindevelopmaster等の保護ブランチにforce pushは絶対に行わないでください。GitHub/GitLabの設定で物理的に禁止するのが安全です。保護ブランチでの取り消しは必ずrevert+PRで行います。

force push前のチェックリスト

実行前に必ず確認

  • このブランチは自分しか触っていないか?
  • 保護ブランチではないか?(GitHub Settingsで確認)
  • 他メンバーがこのブランチをベースに作業していないか?
  • PRをレビュー中のブランチで、レビュアーの作業が無駄にならないか?
  • 最新のgit fetch originを済ませたか?

誤ってmainやdevelopに直接pushしてしまった

「PRを作らずにmainpushしてしまった」は頻出事故です。基本方針はrevertで打ち消してから、そのコミットを正しいブランチに移動します。

mainに誤push後のリカバリ
# 1. 打ち消したいSHAを確認(直近のpushコミット)
git log --oneline -3

# 2. 新しい作業用ブランチを作って、そこにコミットを持っていく
git switch -c feature/recover-push <誤pushしたSHA>
git push -u origin feature/recover-push

# 3. main に戻ってrevertで打ち消し
git switch main
git pull origin main
git revert <誤pushしたSHA>
git push origin main

# 4. feature/recover-push からPRを出して通常のレビューフローに乗せる

ポイント:誤pushに気付いた瞬間に「force pushで消せばいい」と考えがちですが、CIが走ったりSlack通知が飛んでいたりする可能性があるため、履歴は残したままrevertで打ち消す方が後々のトラブルが少ないです。保護ブランチ設定が未導入なら、これを機にGitHubのBranch protection rulesを有効化しましょう。

保護ブランチの運用詳細はGitHub公式ドキュメントやDevOps系のガイドを参照してください。この記事では取り消しの手順にフォーカスします。

機密情報(APIキー・パスワード)をpushしてしまった

これはpush取り消しで最も緊急度が高いケースです。GitHubのパブリックリポジトリならpushした瞬間に世界中のbotがクロールし始めます。「取り消す」より「既に漏洩したものとして扱う」のが鉄則です。

絶対に最初にやること:漏洩した認証情報を即座にrotate(無効化・再発行)してください。AWSキー・DBパスワード・APIトークン・SSH秘密鍵——すべて使えなくしてから、Git側の履歴処理に進みます。履歴を消しても、一度pushされた情報は既にキャッシュ・ミラー・botに取得されている前提で動きましょう。

緊急対応フロー

機密pushの緊急対応
# STEP 1: 認証情報を即時rotate(AWS Console・DB・APIサービス側で対応)
# STEP 2: .gitignore に該当ファイルを追記
echo "config/secrets.env" >> .gitignore
git add .gitignore
git commit -m "chore: add secrets.env to .gitignore"
git push

# STEP 3: git filter-repo で履歴から該当ファイルを完全削除
# (BFG Repo-Cleaner でも可。filter-branch は非推奨)
pip install git-filter-repo
git filter-repo --path config/secrets.env --invert-paths

# STEP 4: 履歴書き換え後は全員再clone推奨。強制pushで共有
git push origin --force --all
git push origin --force --tags

# STEP 5: GitHubのSecret Scanningアラートを確認(有効化されていれば)
# STEP 6: 漏洩対象に応じて社内インシデント報告

注意:filter-repoは履歴を全面書き換えるため、全メンバーの再cloneが必要になります。チームに事前通知し、進行中のPR・作業中のローカル作業を退避してもらってから実行してください。詳細は履歴に含まれる機密情報を完全に削除する方法を参照。

force pushで壊したリモートをreflogで救う

git push --forceで誤って他人のコミットを消してしまった、間違ったブランチをforce pushしてしまった——そんなときもpush直後なら救済可能です。リモート側のreflog(サーバーサイド)、もしくはチームメンバーのローカルreflogから失われたSHAを探し出します。

force push後のリカバリ
# ローカルreflogでpush前のSHAを探す
git reflog
# 出力例:
#   a1b2c3d HEAD@{0}: reset: moving to HEAD~3
#   e4f5g6h HEAD@{1}: commit: 消してしまったコミット

# 消えたSHAが分かれば、そこからブランチを作って復元
git switch -c recover/lost-work e4f5g6h
git push -u origin recover/lost-work

# GitHub側のreflogを使う(管理者権限があれば)
# Repo設定 → Events / APIで確認 or GitHub Support に問い合わせ

ポイント:消えたように見えるコミットも、GitHubのサーバー側には通常約90日間残っています(参照されなくなっただけ)。PRをベースに作業していた場合は、PRページのcommitsタブから消えたSHAを確認できることもあります。諦める前にまずPRとreflogを確認しましょう。

チーム内でまだそのブランチを触っている人がいれば、その人のローカルに完全な履歴が残っています。依頼してgit pushしてもらえば元に戻せます。

取り消し方法の選び方フロー

実務でpush後に直面する代表的ケースと推奨アクションをまとめました。

状況 推奨アクション
個人ブランチでpush内容が間違っていた resetpush --force-with-lease
共有ブランチにpushしてしまった git revert <SHA>+push
マージをpushしてしまった git revert -m 1 <マージSHA>
mainに誤pushした(PR経由でない) 新ブランチに移動+mainでrevert
機密情報をpushした rotate→filter-repoで履歴削除+force push
force pushで壊してしまった reflogでSHA特定→復元ブランチ
push直後で他人がpullしていない resetpush --force-with-leaseも可

チーム運用:取り消しの影響を最小化する

pushの取り消しは技術的な操作に加えてチームへのコミュニケーションが重要です。無言で履歴を変更すると、他メンバーが混乱してpull失敗の原因になります。

push取り消し時の動き方

  • force pushする前にSlack/チャットに予告する(対象ブランチ・影響範囲)
  • 他メンバーにgit fetch --all --prune+作業退避を依頼
  • 機密情報絡みならセキュリティチームに即時エスカレート
  • 取り消し後は「何をどう直したか」をPRやコミットメッセージに残す
  • 再発防止:Branch protection rules・pre-commit hook・Secret Scanning導入
他メンバーが同期する際のコマンド
# force push後にこれを各メンバーが実行
git fetch origin

# 作業中のブランチを保全してから
git stash

# リモートに合わせてリセット(個人ブランチのみ)
git reset --hard origin/<branch>

# もしくは一度ブランチを消して取り直す
git switch main
git branch -D <branch>
git switch <branch>

やってはいけない落とし穴

保護ブランチにforce pushする

mainやdevelopといった共有ブランチにforce pushすると、他メンバーのpull時にnon-fast-forwardエラーが発生し、最悪の場合はローカル変更をrebase/mergeで失う人が出ます。必ずrevertで打ち消しコミットを追加する方式にしてください。GitHubのBranch protection rulesでforce pushを物理的に禁止するのが根本対策です。

機密情報を「revertで打ち消せば解決」と考える

revertは履歴に打ち消しコミットを追加するだけで、過去のコミット内に含まれる機密情報はそのまま残ります。APIキーはgit log -pで誰でも拾えます。rotate→filter-repoでの履歴書き換えまでがセットです。

push –force を –force-with-lease と同じ感覚で使う

--forceは他人の作業を問答無用で消します。共同作業ブランチで使うと、本人が気付かないうちにチームメンバーの作業を破壊する事故が起きます。--force-with-leaseを既定にし、--forceは最終手段に留めましょう。gitエイリアスでforcepush = push --force-with-leaseと登録する運用が有効です。

force push後に事実を共有しない

履歴が書き換わった事実をチームに伝えないと、他メンバーのpull時に混乱を招きます。「force pushしました」「対象ブランチはxxx」「時刻はyyy」を明示し、メンバーにfetch&必要ならreset --hard origin/xxxを依頼しましょう。

force pushで消したコミットを諦める

push直後(90日以内)ならローカルreflog・GitHubサーバー側・他メンバーのローカルのいずれかに必ず履歴が残っています。慌ててさらに操作する前にgit reflogを確認し、SHAを特定してから救済ブランチを作りましょう。

よくある質問

Qpush直後に気付いた。force pushとrevert、どちらが良い?
Aそのブランチが「自分しか触らない個人ブランチ」かつ保護ブランチでない場合は--force-with-lease、それ以外はrevertです。迷ったらrevertを選ぶのが安全です。
Qrevertしたコミットをあとから再度取り込みたい
A打ち消しコミット自体をさらにgit revertするか、該当コミットを別ブランチでcherry-pickして持ち込みます。単純なmergeでは打ち消しが勝って取り込まれないケースがあります。
Q–force-with-lease でも stale でエラーになる
Aリモートが自分の認識(origin/xxx)と一致していない状態です。git fetch originでリモート追跡を最新化してから再実行してください。他メンバーがpushしていた場合は、その内容を確認してから上書きするか判断します。
Qパブリックリポジトリに機密情報をpushした。filter-repoで履歴を消せば大丈夫?
A履歴は消えますが既に漏洩した情報は取り戻せません。何より先に認証情報をrotateしてください。filter-repoはあくまで「今後の履歴に残さない」ためのクリーンアップです。
QGitHubでmainにforce pushしたらブランチがロックされた
ABranch protection rulesが有効になっている証拠で、これは正常な動作です。保護ブランチの取り消しは必ずrevert+PR経由で行ってください。どうしても必要な緊急時は管理者権限でルールを一時解除します。
Qmainに誤pushしてしまったコミットを別ブランチで生かしたい
Agit switch -c feature/xxx <誤pushSHA>で新ブランチを作ってpushし、mainではgit revert <誤pushSHA>で打ち消すのが定石です。詳細は過去コミットから新ブランチを作る方法も参考になります。
Qpush後にコミットメッセージだけ直したい
A個人ブランチならgit commit --amendpush --force-with-lease、共有ブランチなら既存メッセージは放置し、次のコミットで注記するのが無難です。詳細はコミットメッセージの変更方法を参照。

関連記事

まとめ

  • pushの取り消しは原則revertで打ち消しコミットを追加するのが最も安全
  • 個人ブランチかつ保護ブランチ外なら--force-with-leaseで履歴書き換え可
  • --forceは避け、--force-with-leaseを既定にする
  • 機密情報pushは「rotate最優先」→filter-repoで履歴削除
  • mainへの誤pushは「新ブランチに移動→mainでrevert」が定石
  • force pushで壊してもreflog・GitHubサーバー・メンバーのローカルから救済できる
  • 技術的操作に加えチームコミュニケーションが欠かせない

push後の取り消しは「何を直したいか」ではなく「誰に影響するか」で判断するのがコツです。自分だけが影響する個人ブランチならforce系で素早く、共有ブランチならrevertで丁寧に——この基本を押さえれば、慌てずに正しいリカバリができます。あわせて保護ブランチ設定・Secret Scanning・pre-commit hookといった事故予防の仕組みを整え、そもそも取り消しが必要な状況を減らしていきましょう。