Git - 特定のコミットを削除、元に戻す(reset、revert)

端末からgitコマンドで特定のコミットを削除したり、特定のコミットに戻る方法を紹介します。

1. 特定のコミットに戻す(git reset)

git reset --hard <commit id>命令は以前に反映された特定のコミットに戻り、その後に反映されたコミットはすべて削除する方法です。

たとえば、次のように3つのコミットが反映されている場合、最近反映された2つのコミットを削除し、最初のコミットである ecb42eeに戻りたいときは、

$ git log
commit 1edf17e135a8b4e2996b1cba8eec8d5635469bdd (HEAD -> master)
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:37 2022 +0900

    Add c.txt

commit 5b85a825bff96da466af7dcf21e5a1edb2d96e97
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:23 2022 +0900

    Add b.txt

commit ecb42ee4da1d63caec1282b006b687ee1a74f46f
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:15 2022 +0900

    Add a.txt

次のように git reset --hard <commit id>命令を使用できます。

$ git reset --hard ecb42ee4da1d63caec1282b006b687ee1a74f46f
HEAD is now at ecb42ee Add a.txt

コマンド入力後、 git log を入力してみると最新の commit(HEAD) が ecb42ee になっています。 つまり、 ecb42eeの後に反映されたコミットはすべて削除されました。

$ git log
commit ecb42ee4da1d63caec1282b006b687ee1a74f46f (HEAD -> master)
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:15 2022 +0900

    Add a.txt

上記のリセットコマンドは、以下のように簡単に入力することもできます。ちなみに、 HEADは最新のコミットを指し、 HEAD~1は最も最近のコミットの1つ前のコミットを意味し、 HEAD~2は2つの前のコミットである ecb42eeを意味します。

$ git reset --hard HEAD~2
HEAD is now at ecb42ee Add a.txt

最後に、変更を remote branch に適用すると競合が発生する可能性があるため、-f を使用して強制的に更新する必要があります。

$ git push -f origin <branch name>

1.2 commit を削除せずに、変更を staged 領域に戻す

git reset --soft <commit id>コマンドを使うと、--hardと同じようにcommit idに移動します。

2つの違いは、 --hardは特定のコミットの後に適用したすべてのコミットを削除することを意味します。

$ git reset --soft ecb42ee4da1d63caec1282b006b687ee1a74f46f

$ git log
commit ecb42ee4da1d63caec1282b006b687ee1a74f46f (HEAD -> master)
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:15 2022 +0900

    Add a.txt

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   b.txt
	new file:   c.txt

上記のようにステージング領域に変更がある場合は、一部の内容を変更して再コミットを適用できます。

$ git commit -m "Add b, c files"
[master 95ecebc] Add b, c files
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 b.txt
 create mode 100644 c.txt

$ git log
commit 95ecebc740368ec9f2340b6794cd1b75f52184bf (HEAD -> master)
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:54:13 2022 +0900

    Add b, c files

commit ecb42ee4da1d63caec1282b006b687ee1a74f46f
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:15 2022 +0900

    Add a.txt

2. 特定のコミットの変更を削除し、コミットを登録する(git revert)

特定のコミットの変更をすべて削除し、削除した内容をコミットとして登録する方法です。通常revertと呼ばれます。

例えば、上で紹介したプロジェクトで以下のように最初の commit ecb42ee を revert すると、現在のコードからこの修正のみが削除されます。

$ git revert ecb42ee4da1d63caec1282b006b687ee1a74f46f
Removing a.txt
[master 6581856] Revert "Add a.txt"
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 a.txt

git logで履歴を確認すると、 Revert "Add a.txt"という名前で、最初のcommitの修正を削除する新しいcommitが登録されました。

$ git log
commit 65818566596380b0c888e9b840c5d61120bf72b9 (HEAD -> master)
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:55:56 2022 +0900

    Revert "Add a.txt"

    This reverts commit ecb42ee4da1d63caec1282b006b687ee1a74f46f.

commit 1edf17e135a8b4e2996b1cba8eec8d5635469bdd
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:37 2022 +0900

    Add c.txt

commit 5b85a825bff96da466af7dcf21e5a1edb2d96e97
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:23 2022 +0900

    Add b.txt

commit ecb42ee4da1d63caec1282b006b687ee1a74f46f
Author: farfs <farfs.dev@gmail.com>
Date:   Sun Sep 18 15:32:15 2022 +0900

    Add a.txt

resetとrevertの違いを比較すると、 git resetは以前のコミットに戻り、その後に反映したコミットをきれいに削除しました。

git revertは特定のコミットの変更を削除しますが、以前に保存したコミットは削除せずにrevertの新しいコミットを追加します。 また、revertを使用した場合、Remote branchと衝突が発生しないため、resetのように -fを使ってプッシュする必要はありません。

codechachaCopyright ©2019 codechacha