Git/GitHub

git pushを取り消す2つの方法

  1. git revertでコミットを打ち消す
  2. git resetでコミットをなかったことにする

git revertは対象のコミットを打ち消すためのコミットを行います。コミットログとしては、対象のコミットとそれを打ち消すためのコミットの2つが残ります。過去の履歴を書き換えないので、安全に取り消しが行えます。

git resetは対象のコミットをコミットログから削除します。いわゆる歴史の書き換えですね。コミットログは見やすくなる一方、歴史を書き換えるので、チーム開発をしている場合にコンフリクトが起きる可能性があります。

git revertでコミットを打ち消す

# 直前のコミットの内容を打ち消すためのコミットを行う
$ git revert HEAD
or
# 対象のコミットの内容を打ち消すためのコミットを行う
$ git revert コミット番号
# 打ち消したコミットをプッシュする
$ git push origin HEAD
view raw git.sh hosted with ❤ by GitHub

git push origin HEADの意味については、以下記事をご覧ください。
git pushするときは「git push origin HEAD」が便利でおすすめ - Reasonable Code

コマンドのみだとわかりづらいので、実際に試してみます。

# masterブランチで作業している
$ git branch
* master
$ git log --oneline
1c5a640 (HEAD -> master) Initial commit
# 中身は空
$ cat README.md
# README.mdを編集する(誤った内容)
$ echo "Hallo World" > README.md
# README.mdをコミット&プッシュする
$ git add README.md
$ git commit -m "modify README.md"
$ git push origin master
# ここで、編集内容が間違っていたことに気づく
$ cat README.md
Hallo World
# 直前のコミットの内容を取り消したい
$ git log --oneline
3aff6a0 (HEAD -> master, origin/master) modify README.md
1c5a640 Initial commit
# 直前のコミットの内容を打ち消すためのコミットを行う
$ git revert HEAD
# 編集画面が開くので、コミットコメントを適宜編集し、「:wq」で閉じる
-------------------------------------------------------------------
Revert "modify README.md"
This reverts commit 3aff6a0cfe4d5908fd1978e3cbe36675afaf45a5.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
# modified: README.md
#
-------------------------------------------------------------------
# コミットの内容を打ち消すためのコミットが行われている
$ git log --oneline
245924b (HEAD -> master) Revert "modify README.md"
3aff6a0 (origin/master) modify README.md
1c5a640 Initial commit
# 誤った編集内容が元に戻っている
$ cat README.md
# 打ち消したコミットをプッシュする
$ git push origin HEAD
view raw git.sh hosted with ❤ by GitHub

git revertはコミットを打ち消すためのコミットを行っていることがわかります。取り消したいコミットもコミットログとして残るので、歴史を書き換えることはありません。このことから、git revertは安全にコミットの取り消しが行える方法といえます。

ただ、不要なコミットが残るので、コミットログが見づらくなります。

git resetでコミットをなかったことにする

# 直前のコミットを取り消す、変更した内容は取り消さない
$ git reset --soft HEAD^
or
# 直前のコミットと変更した内容を取り消す
$ git reset --hard HEAD^
# 強制的にプッシュする(歴史を書き換えるため)
$ git push -f origin HEAD
view raw git.sh hosted with ❤ by GitHub

コマンドのみだとわかりづらいので、実際に試してみます。

# masterブランチで作業している
$ git branch
* master
$ git log --oneline
9b78abe (HEAD -> master) Initial commit
# 中身は空
$ cat README.md
# README.mdを編集する(誤った内容)
$ echo "Hallo World" > README.md
# README.mdをコミット&プッシュする
$ git add README.md
$ git commit -m "modify README.md"
$ git push origin HEAD
# ここで、編集内容が間違っていたことに気づく
$ cat README.md
Hallo World
# 直前のコミットの内容を取り消したい
$ git log --oneline
c371b39 (HEAD -> master, origin/master) modify README.md
9b78abe Initial commit
# 直前のコミットをなかったことにする(変更した内容はそのまま)
$ git reset --soft HEAD^
# コミットがなかったことになっている
$ git log --oneline
9b78abe (HEAD -> master) Initial commit
# 変更した内容は取り消されていない
$ cat README.md
Hallo World
# 歴史を書き換えようとするためエラーが発生する
$ git push origin HEAD
To https://github.com/donchan922/practice2.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/donchan922/practice2.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
# 強制的にプッシュする
$ git push -f origin HEAD
view raw git.sh hosted with ❤ by GitHub

git resetは誤ったコミットをなかったことにしているのがわかります。コミットログから消えているので、歴史を書き換えたことになります。コミットログが綺麗になる一方、チーム開発で他の人が同一ブランチで作業している場合、コンフリクトが起きる可能性もあるので使い方には要注意です。

まとめ

  1. git revertでコミットを打ち消す
  2. git resetでコミットをなかったことにする

参考リンク

-Git/GitHub

S