🐧

Git コマンドの取り消し方

2021/03/03に公開

よく使うコマンドとその取り消し方

  • git を使用していて,「やっぱりやめよう」と思ったときに毎回操作の取り消し方をググっていることに気づいたので自分の勉強を兼ねてシンプルなチートシートを作成します

git add

  • ローカルの編集をコミットするために登録する(stage する)

ファイルを指定してgit add を取り消し

git reset path/to/file

全ファイルのgit add を取り消し

git reset

git checkout

  • ローカルの編集を破棄する
  • 何故破棄したいのか
  • もしかしてあなたがしたいのはgit stash では?

ファイルを指定してgit checkout

git checkout path/to/file

git checkout (ローカル変更点の破棄)を取り消し

  • できない
  • 次からgit stash を使おう

git commit

  • 編集をローカルリポジトリにコミットする(自己言及?)

直前のgit commit に編集を追加

  • git commit --amend で直前のコミットを上書きできる
git add -A
git commit --amend

直前のgit commit のコメントを修正

  • git commit --amend はコミット内容の変更よりもこの用途でよく使用する印象です
git commit --amend "add bug"

git commit --amend の取り消し

  • 落ち着け
  • 失敗を取り返そうとして墓穴を掘るのはやめよう
git reset --soft HEAD@{1}

直前のgit commit の取り消し

  • なぜ取り消したいのか
  • もしかしてあなたがしたいのはgit revert では?
    • たいていのケースではgit のhistory 上を行ったり来たりするより,取り消したいコミットを打ち消して前進する方が安全です
    • コミット履歴が汚れる → 冗長なコミットは後でgit rebase すればOK
git reset --hard HEAD^

git revert

  • 特定のコミットを打ち消す
  • 時系列を遡らず,新たなコミットとして打消しコミットが追加されるため,多人数開発でも何をしたか分かりやすい

直前のコミットをgit revert

git revert --no-edit HEAD

コミットID を指定してgit revert

# コミットID の確認
git log
git revert --no-edit {コミットID}

複数コミットをまとめてgit revert

  • コミットメッセージに最後にrevert した物のID しか載らないため注意
  • 一件ずつgit revert してからgit rebase でコミットをまとめるのも手
git revert -n {コミットID}
git revert -n {コミットID}
git revert -n {コミットID}
git commit --no-edit

直前のコミットからX件をまとめてgit revert

  • コミットメッセージに最後にrevert した物のID しか載らないため注意
  • 一件ずつgit revert してからgit rebase でコミットをまとめるのも手
# 3件まとめてrevert する例
git revert -n HEAD~3..HEAD
git commit --no-edit

git revert の取り消し

  • git revert したものの気が変わった場合
  • 打消しコミットを作成しているだけでgit revert が行ったことはgit commit と同じ
  • 個人的にはこのケースくらいでしかgit reset --hard の出番がない印象
git reset --hard HEAD^

git revert をgit revert

  • revert をrevert することももちろん可能
  • 作業ブランチを切る前に変なコードを一時退避する時など稀に行う
git revert --no-edit {取り消したいrevert コミットのID}

git revert -n の取り消し

  • まとめてrevert しようと思ったけど気が変わった場合
git revert --abort

git push

  • ローカルリポジトリの内容をリモートリポジトリに送信する

git push の取り消し

  • なぜ取り消したいのか
  • 落ち着いて該当コミットをgit revert してpush し直す方が安全
git revert --no-edit HEAD
git push origin HEAD
  • どうしてもなかったことにしたい場合はローカルリポジトリ上でcommit を取り消してからリモートに対してforce push する
git reset --hard HEAD^
git push -f origin HEAD

git merge

  • 別ブランチの内容を現在のブランチに取り込む

git merge の取り消し(CONFLICT 発生時)

  • git merge したもののCONFLICT が発生して心が折れた場合
git merge --abort

git merge の取り消し(merge 成功時)

  • git merge は成功したがやっぱりまだ取り込みたくなかった場合
  • merge コミットが作成されているのでcommit の取り消しと同じ
  • push 済みならcommit の取り消し同様git revert するのが安全
git revert --no-edit HEAD
  • ローカルでマージしただけの状態ならまだ取り返しがつくのでgit reset しても大丈夫
git reset --hard HEAD^

git pull

  • リモートリポジトリの内容を取り込む
  • やってることはgit fetch してからgit merge しているだけなので
    取り消し方はgit merge と同じ

git rebase

  • コミット履歴を編集する

git rebase の取り消し(CONFLICT 発生時)

git rebase --abort

git rebase の取り消し(rebase 成功時)

git reset --hard ORIG_HEAD

git reset

  • コミットの取り消し
  • 原則ローカル操作の取り消しにだけ使用してリモートにpush 済みのコミットはいじらない
  • この記事の主役?git revert で良いときはgit revert するので出番は少ない

基本の使い方

  • git reflog で操作ログを参照
git reflog
# 出力例
b794598 (HEAD -> master) HEAD@{0}: commit: perfect commit
9487bac HEAD@{1}: commit: super commit
576cd31 HEAD@{2}: commit: second commit
2ddfe2b HEAD@{3}: commit (initial): first commit
  • 戻りたい時点を指定してreset
# second commit したところに戻りたい場合
git reset HEAD@{2}
  • git 上のcommit だけ取り消してローカルファイルはほっといて欲しい(ワーキングツリーを残したい)場合は--soft オプションをつける
  • ローカルファイルもreset 先の状態に上書きして欲しい場合は--hard オプションをつける

git reset の取り消し

  • 落ち着け
  • git reset に失敗するとテンパるがgit reflog すれば履歴が残っているので
    git resetgit reset する」ことで挽回できる
git reflog
# 出力例
576cd31 (HEAD -> master) HEAD@{0}: reset: moving to HEAD@{2}
b794598 HEAD@{1}: commit: perfect commit
9487bac HEAD@{2}: commit: super commit
576cd31 (HEAD -> master) HEAD@{3}: commit: second commit
2ddfe2b HEAD@{4}: commit (initial): first commit
# 直前のgit reset をなかったことにする場合
git reset --soft HEAD@{1}

Discussion