32.

git pushを取り消す方法|reset --hard+push -fとrevertの使い分け

編集
この記事の要点
  • push を取り消すとはリモートブランチの先端を過去のコミットに戻す操作で、他の開発者の作業を破壊しうる非常に危険な操作である
  • 基本手順は git reset --hard <戻したいコミット>git push -f origin <branch>
  • リモートが --shared 付きベアリポジトリの場合は push -f が拒否されるため、リモート側で git reset --soft を直接実行する
  • 本番運用のブランチ(main / master / release)には原則 force push しない。代わりに git revert で打ち消しコミットを積む
  • 実施前に必ずバックアップブランチgit branch backup-YYYYMMDD)を取り、チームに事前告知する
⚠️ 本作業は非常に危険です。 リモートブランチの履歴を改変するため、他の開発者の作業が消える / 強制 push をした側だけ pull / push できなくなる、といった事故を起こします。必ずバックアップを取り、チーム合意の上で実施してください。

push 取り消しの 3 つの方針

方針概要安全性
A. revert で打ち消す新しいコミットで変更を相殺。履歴は残る◎ 推奨
B. reset --hard + push -f履歴を強制的に過去へ巻き戻す△ 個人ブランチでのみ
C. リモート側で reset--shared 付きベアリポジトリ等で B が拒否されたときの最終手段× 共有リポへの直接操作

A. 推奨:git revert で打ち消す

最も安全な方法です。元の履歴は残したまま「相殺するコミット」を追加するだけなので、他の開発者を巻き込んだ事故になりません。

# 取り消したいコミット ID を確認
git log --oneline -10

# 打ち消しコミットを作成(メッセージは自動生成)
git revert c545149

# リモートへ通常 push
git push origin master

複数コミットを一気に打ち消したい場合は git revert c545149..HEAD のように範囲指定できます。マージコミットを revert したい場合は -m 1 を付けます。

B. 強制:reset --hard + push -f

「履歴から完全に消したい」「個人ブランチで誰にも影響しない」というケース限定です。main / master / release 等の共有ブランチではやらないでください。

# まずバックアップブランチを作る
git branch backup-before-reset

# 戻したいコミット(=この時点を最新にする)まで巻き戻す
git reset --hard c545149

# リモートへ強制 push
git push -f origin master

c545149 の部分には戻したいコミットのリビジョン番号を指定します。HEAD~1 のように相対指定も可能(直前 1 件を取り消し)。

失敗した場合に備えて git reflog で復旧できます。reflog は通常 90 日間残るので、慌てずに git reset --hard HEAD@{1} 等で元の HEAD に戻せます。

C. --shared 付きベアリポジトリで拒否されるとき

リモートが git init --shared --baregit clone --bare で作られている場合、デフォルトで非 fast-forward な push(つまり force push)を拒否します。具体的には以下のメッセージで弾かれます。

remote: error: denying non-fast-forward refs/heads/master (you should pull first)

この場合はリモートリポジトリ側に SSH 接続して、サーバ上で直接ブランチを戻します。

# サーバへ SSH 接続
ssh user@git-server

# ベアリポジトリへ移動
cd /srv/git/myrepo.git

# 該当コミットへ HEAD を巻き戻す
git reset --soft c545149

--soft はワークツリーを持たないベアリポジトリでも安全に使えます。実施後は各開発者に「先頭が変わったので git fetch && git reset --hard origin/master してほしい」と必ず連絡してください。

事前に必ずやること

  • git branch backup-YYYYMMDDバックアップブランチを作る
  • 関係するメンバーに force push の時刻と対象ブランチを事前告知する
  • 取り消し対象のコミット ID(git log --oneline)と戻したい先のコミット ID をメモする
  • その時点の作業を git stash ですべて退避しておく

force push 後のチームメンバーの復旧手順

誰かが force push した後、他の開発者は通常の git pull ではコンフリクトしてしまいます。以下のようにリモートの状態に強制的に合わせてもらいます。

# 最新を取得
git fetch origin

# ローカルブランチを破棄してリモートに合わせる
git reset --hard origin/master

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 用語一覧
  2. エラー一覧
  3. git本体のインストール(Linux)
  4. Linuxサーバーへのgit導入とクライアントのセットアップ
  5. リモートリポジトリをローカルリポジトリとしてクローンする方法
  6. リモートとローカルのリポジトリを同期(pull)する方法
  7. 設定の確認
  8. gitユーザー名とemailの設定
  9. リモートリポジトリの作成
  10. ローカルリポジトリの作成
  11. 新規ファイル/ディレクトリをインデックスに登録
  12. インデックスの登録状態を確認
  13. ローカルリポジトリの変更をコミット
  14. コミット履歴の確認
  15. クライアントからリモートリポジトリの接続設定、確認、削除
  16. リポジトリへのプッシュ
  17. リモートリポジトリからクライアントへのSSHクローン
  18. リモートとローカルの差分表示
  19. バージョンの確認
  20. プロキシの設定
  21. ローカルをリモートリポジトリの状態に戻す
  22. ブランチの作成, 一覧表示, 切り替え
  23. ブランチのマージと削除
  24. リベース
  25. .gitignoreの書き方
  26. .gitignoreの設定が反映されない場合
  27. 特定のファイルをgitの管理から外す方法
  28. 参照(ORIG_HEAD, HEAD, FETCH_HEAD)
  29. git rm [-r --cached] の取り消し
  30. 一部のディレクトリ/ファイルのみをリポジトリから復元する方法
  31. ローカルとリモートリポジトリの有無を同期
  32. pushの取消し方法
  33. マージツールの起動方法
  34. Gitで「MERGING」の状態

最近更新/作成されたページ