gitでpush済みのコミットを取り消す方法

誤ってpushしたコミットを取り消す必要が出たのでやり方を調べました。

結論

push済みのコミットを取り消すにはgit resetgit revert を使う。

  • git reset: コミットを取り消す、強制pushする
  • git revert: 打ち消しコミットを作成する、追加pushする

コミットの指定方法について

git resetgit revert で使用するコミットの指定方法です。

  • HEAD: 最新のコミット
  • HEAD^: 直前のコミット
    • HEAD~も同じ意味
  • HEAD~n: 直前のコミット + n個分のコミットを指定
    • HEAD~3HEAD~{3}HEAD^^^HEAD~~~は同じ意味
  • git log で出力されるコミットIDで直接コミットを指定
  • HEAD@で代用できる
    • HEAD~@~ は同じ意味
    • HEAD~3@~3 は同じ意味
  • ~^で代用できるが微妙に意味が異なる点に注意する
  • zshの場合は^\^ と入力する
# コミットの指定例

# 直前のコミットを指定
$ git reset HEAD~

# 4つ前までのコミットを指定(HEAD + コミット数)
$ git reset HEAD~3

# コミットIDで指定
$ git log
...
commit e96db8f7687a33246509cb05913b5db2ecc9c5b0 # 指定するコミットID
Author: 
Date:   
...
$ git reset コミットID

[git reset (--hard/--soft)]ワーキングツリー、インデックス、HEADを使いこなす方法 - Qiita

【やっとわかった!】gitのHEAD^とHEAD~の違い - Qiita

git reset

コミットを取り消すコマンドです。

Git - git-reset Documentation

  • 歴史改変になる点に注意する
  • コミット取り消し後の再push時は強制pushが必要

git resetのオプション

git reset で良く使うオプションです。

  • --soft: コミットのみ取り消し
  • --mixed: コミット、インデックスのみ取り消し(resetコマンドのデフォルト)
  • --hard: コミット、インデックス、ワーキングツリー全てを取り消し

[git reset (--hard/--soft)]ワーキングツリー、インデックス、HEADを使いこなす方法 - Qiita

git resetを使ってpush済みのコミットを取り消す

例) push済みのコミットを取り消したい。

  • 直前のコミットのみ取り消したい
  • 作業途中なのでgit add した内容は残したい
# 直前のコミットの取り消し
$ git reset --soft HEAD~

# 強制push
$ git push -f

git resetを取り消す

git reset 自体を取り消したい場合はORIG_HEAD を指定する。

$ git reset --hard ORIG_HEAD

ORIG_HEAD とは最新の一つ手前のコミットに対するハッシュ値です。

GitのHEAD, ORIG_HEAD, FETCH_HEAD, MERGE_HEADとは? - Qiita

git revert

コミットを打ち消すコミットを作成するコマンドです。

Git - git-revert Documentation

  • コミットを修正したことが残るのでreset に比べたら安全
  • 不要なコミットが増えてしまう
  • コミット修正後のpushはコンフリクトしない

git revertを使ってコミットを取り消す

例) push済みのコミットを取り消したい。

  • 直前のコミットのみ取り消したい
  • 取り消しのコミットログを残したい
# 直前のコミットの打ち消しコミットを作成
$ git revert HEAD

# 追加push
$ git push

まとめ

思ったより複雑で理解するのに時間が掛かってしまった。 過去改変系の操作は全然覚えていないのでガンガン使って覚えていきたい。

参照

[git reset (--hard/--soft)]ワーキングツリー、インデックス、HEADを使いこなす方法 - Qiita

【やっとわかった!】gitのHEAD^とHEAD~の違い - Qiita

[git reset (--hard/--soft)]ワーキングツリー、インデックス、HEADを使いこなす方法 - Qiita

GitのHEAD, ORIG_HEAD, FETCH_HEAD, MERGE_HEADとは? - Qiita

Git - Documentation