push済みのコミットを打ち消す:git revertで履歴を残したまま元に戻す手順

push済みのコミットはgit revertで打ち消すと、元の履歴を消さず、force pushも使わずに送れます。打ち消すコミットIDの選び方、結果の確かめ方、競合で止まったときの戻し方を練習用フォルダーで確認します。

目次
  1. push済みなら、打ち消すコミットを新しく足す
  2. reset --softとrevertで変わるもの
  3. 練習用フォルダーを作り、そこへ移動する
  4. 送信先と3件のコミットを用意してpushする
  5. 2件目のコミットだけを打ち消す
  6. force pushなしで送り、送信先を確かめる
  7. 競合で止まったら、解決して続けるか中止する
  8. この記事で扱わない操作
  9. 参考資料

push済みなら、打ち消すコミットを新しく足す

既にpushしたコミットの変更を取り消すなら、git revertを使います。git revertは、指定したコミットが加えた変更を逆向きに適用し、その結果を新しいコミットとして記録します。元のコミットは履歴に残ったままです。

Git公式の説明では、resetはブランチの先頭を動かしてコミットを追加・削除する操作で、履歴を書き換えます。revertは他のコミットの変更を打ち消す新しいコミットを作る操作です。履歴の先頭に1件足すだけなので、取り消したコミットを既に受け取った人の履歴とも食い違いません。

公式の説明では、revertの実行前に作業ツリーがクリーン(HEADのコミットから変更がない状態)であることが必要です。git status --shortでMなどの行が表示されないことを確かめてから始めます。??で始まる行は、まだGitに追加していない未追跡ファイルで、HEADからの変更には当たりません(練習では未追跡ファイルがあってもrevertできました)。

git status --short
git log --oneline
git revert <打ち消すコミットのID>

reset --softとrevertで変わるもの

push前の直近のコミットを作り直すならreset --soft、push済みのコミットを打ち消すならrevert、と使い分けます。

表は横にスクロールできます →

見るものreset --soft HEAD~1git revert
履歴取り消したコミットが一覧から消える元のコミットは残り、打ち消すコミットが1件増える
その後のpushpush済みなら通常のpushは拒否される送信先が先に進んでいなければ通常のpushで送れる
作業ファイル変わらない(変更はステージに残る)打ち消した後の内容になる

練習用フォルダーを作り、そこへ移動する

以下はGitが使えるBash(WSLやGit Bashなど)用です。PowerShellへそのまま貼る例ではありません。実務のリポジトリではなく、まだ存在しないgit-revert-practiceというフォルダーで試します。次の2行は1行ずつ実行し、エラーが出たらそこで止めてください。既に同名フォルダーがある場合は、別の新しい名前を選びます。

mkdirとcdの両方が成功したことを確かめてから、次へ進みます。

mkdir git-revert-practice
cd git-revert-practice

送信先と3件のコミットを用意してpushする

push済みの状態を再現するため、同じフォルダー内に送信先用のリポジトリremote.gitを作り、作業用のworkからpushします。ネットワーク上のサービスには接続しません。名前とメールアドレスは、この練習用リポジトリ内だけに設定する例示値です。

2件目のAdd wrong lineが、誤ってpushしてしまったコミットという想定です。3件目のAdd later fileは、その後に別のファイルを足したコミットです。

最後のgit log --onelineでは、新しい順にAdd later file、Add wrong line、Base fileの3件が表示されます。左端の7桁ほどの英数字がコミットIDで、環境ごとに値が変わります。

git init --bare remote.git
git init work
cd work
git config user.name 'Practice'
git config user.email 'practice@example.invalid'
git remote add origin ../remote.git
printf 'base\n' > note.txt
git add -- note.txt
git commit -m 'Base file'
printf 'wrong line\n' >> note.txt
git add -- note.txt
git commit -m 'Add wrong line'
printf 'later\n' > later.txt
git add -- later.txt
git commit -m 'Add later file'
git push -u origin HEAD
git log --oneline

2件目のコミットだけを打ち消す

打ち消すのは2件目のAdd wrong lineです。この練習では先頭から1つ前なのでHEAD~1と指定します。実務では、git log --onelineで表示された対象のコミットIDを指定すると、指定の取り違えを防げます。

--no-editは、コミットメッセージを編集するエディターを開かずに、Gitが作る既定のメッセージで記録する指定です。この練習では手順を短くするために付けています。公式の説明では、元のコミットを打ち消す理由をメッセージに書くことが強く推奨されています。実務では--no-editを付けずに実行し、開いたエディターで理由を書き足してください。

git revert --no-edit HEAD~1
git log --oneline
cat note.txt
ls
git show --stat --format=%s HEAD

表は横にスクロールできます →

打ち消した後に見るものこの練習での結果
git log --oneline先頭にRevert "Add wrong line"が増え、元の3件も残って計4件
cat note.txtbaseの1行だけ(wrong lineが消える)
lslater.txtは残る(3件目の変更はそのまま)
git show --stat --format=%s HEADnote.txtの1行削除だけを含む

force pushなしで送り、送信先を確かめる

打ち消すコミットは先頭に1件足しただけなので、通常のgit pushで送れます。push前のgit status --short --branchでは、1行目の末尾に[ahead 1]と表示されます。pushの後は[ahead 1]が消えます。1行目に表示されるブランチ名は、Gitの設定によってmasterまたはmainなどになります。

最後の行は、送信先のremote.gitで先頭のコミットを表示します。Revert "Add wrong line"が表示されれば、送信先にも反映されています。

共有ブランチで、自分より先に他の人がpushしていると、revertのコミットでも通常のpushはrejectedと表示されて拒否されます(練習で、別の作業フォルダーから先にpushして確認)。このときforce pushは使わないでください。他の人のコミットが送信先から消えます。git pullなどで送信先の変更を取り込んでから送り直します。取り込み方の手順はこの記事では扱いません。

比較のため、この練習で同じ状態からreset --soft HEAD~1で先頭を戻してpushすると、送信先にあるコミットを失う更新(fast-forwardではない更新)になるため、通常のpushはrejectedと表示されて拒否されました。

git status --short --branch
git push
git status --short --branch
git --git-dir=../remote.git log --oneline -1

競合で止まったら、解決して続けるか中止する

打ち消すコミットの後に、同じ行を別のコミットが書き換えていると、revertは競合(CONFLICT)で止まります。git status --shortでは、競合したファイルの左にUUと表示されます(両方の変更がぶつかって未解決という意味です)。

競合したファイルには、<<<<<<<・=======・>>>>>>>で始まる行が入ります。残したい内容に書き直してこの3種類の行を消し、git addで解決済みにしてからgit revert --continueで続けます。--continueではメッセージを確認するエディターが開き、保存して閉じると打ち消しのコミットが記録されます。

打ち消しをやめるなら、git revert --abortで実行前の状態に戻ります。練習では、1件目で行を足し、2件目でその行を書き換えるコミットを追加してから1件目を打ち消し、競合を起こしました。--abortの後は先頭のコミットが実行前と一致し、git status --shortは出力なしでした。解決して--continueした場合は、Revert "..."のコミットが記録され、git status --shortは出力なしになりました。

revertが書き換えるファイルにコミットしていない変更があると、「Your local changes to the following files would be overwritten」と表示されて始まりません(練習で確認)。公式の説明どおり作業ツリーをクリーンにするため、その変更を先にコミットするか退避してから、もう一度実行します。

git status --short
git add -- <解決したファイル>
git revert --continue

# 打ち消しをやめる場合
git revert --abort

この記事で扱わない操作

マージコミットの打ち消しには、どちらの親を基準にするかを-mで指定する必要があり、公式は後のマージにも影響すると注意しています。複数のコミットをまとめて打ち消す操作も含め、この記事では扱いません。

打ち消しのコミットをさらにrevertすると、元の変更が戻り、メッセージはReapply "..."で始まります。繰り返すとメッセージが読みにくくなるため、公式は短く分かりやすい文に書き直すよう勧めています。

push前の直近のコミットを作り直す場合は、関連記事「直前のコミットを取り消す:git reset --softで変更をステージに残す手順」を参照してください。

2026年10月2日、WSLのLinux・Git 2.53.0・非rootユーザーで掲載例を実行しました。打ち消し前後の履歴とファイル、pushの前後のブランチ状態、送信先の先頭コミット、競合時の--abortと解決後の--continue、他の人が先にpushした場合の拒否を照合しています。送信先は同じパソコン内のリポジトリで、ホスティングサービスへの送信や実務リポジトリでの動作は、この検証に含みません。

参考資料