gitではコミットを間違てしてしまった場合など、過去のコミットを取り消したい場合があります。そんなときに使えるコマンドにgit revertがあります。
ここではgit reverでできることや実際の使い方について実例を踏まえてまとめています。
git reverとは何か?使い方
git revertは指定したコミットの内容を打ち消して、新しいコミットを作成する処理です。
以下のように打ち消したいコミットを指定して実行します。
git revert <打ち消したいコミット>
実行後にエディタが立ち上がるので、コミットメッセージを入力します。
なお、revertとは「元に戻す」という意味です。
git revertの処理内容のイメージ
例えば以下のようなA~Bのコミット履歴があるときに、コミットBの内容を打ち消したいとします。
#コミット履歴(A〜D)
A---B---C---D
master
その場合「git revert B」を実行します。
#コミットBの作業を打ち消す
$ git revert B
A---B---C---D---D'
master
すると、コミットBの編集内容を削除した、状態の新しいコミットD’が生成されます。
コミット履歴の中でコミットBがなくなっていないのがポイントです。
git revertの実例
例えば以下のようなコミットログがあるとします。
$ git log --oneline
0701d9d (HEAD -> test, second/aa, origin/aa, aa) [U]docker-compose add webpack port 3035
a90d4ef [U]content-security-policy(CSP) enable webpack-dev-server
6adca49 [A]destroyメソッド & Modal追加
この中で、3つ目のコミット「6adca49」の内容を取り消したい場合は以下のようにします。
$ git revert 6adca49
すると、エディタが起動し次のような内容が表示されます。
Revert "[A]destroyメソッド & Modal追加"
This reverts commit 6adca498b4dbdc4df8c18fe15a713507b80222d6.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch test
# Your branch is up to date with 'origin/aa'.
#
# Changes to be committed:
# modified: app/controllers/api/pj1/clients_controller.rb
# deleted: app/javascript/components/Modal.vue
# modified: app/javascript/components/clients/Clients.vue
# modified: config/routes.rb
#
VScodeの場合はVScode内で新しいファイルが起動します。
もしvimが起動した場合の使い方は以下をご参考ください。
【vi(vim)とは何か?】vimテキストエディタを使う方法とコマンド一覧
一番上に表示されている「Revert “[A]destroyメソッド & Modal追加”」の部分が、git revert後に作成したコミットに付与されるコミットメッセージです。
必要に応じてこの内容を編集してください。
なお、#の部分はコメントアウトなので無視して問題ありません。
今回はコミットメッセージを「Revertで”[A]destroyメソッド & Modal追加”を打ち消しました。」として保存して閉じます。
すると以下のように実施した内容が表示されます。
$ git revert 6adca49
Removing app/javascript/components/Modal.vue
[test f5351fe] Revertで"[A]destroyメソッド & Modal追加"を打ち消しました。
4 files changed, 4 insertions(+), 154 deletions(-)
delete mode 100644 app/javascript/components/Modal.vue
コミット履歴を確認します。
$ git log --oneline
f5351fe (HEAD -> test) Revertで"[A]destroyメソッド & Modal追加"を打ち消しました
。
0701d9d (second/aa, origin/aa, aa) [U]docker-compose add webpack port 3035
a90d4ef [U]content-security-policy(CSP) enable webpack-dev-server
6adca49 [A]destroyメソッド & Modal追加
指定した「6adca49」を打ち消したコミットとして新たに「f5351fe」が最新のコミットになっていることがわかります。
このコミットの内容を見てみましょう。
実行内容の詳細はgit show <コミット番号>
で確認できます。
$ git show f5351fe
commit f5351fe4e4634f66c15e1d819222659d05967348 (HEAD -> test)
Author: author <example@gmail.com>
Date: Thu Jan 27 18:55:10 2022 +0900
Revertで"[A]destroyメソッド & Modal追加"を打ち消しました。
This reverts commit 6adca498b4dbdc4df8c18fe15a713507b80222d6.
diff --git a/app/controllers/api/pj1/clients_controller.rb b/app/controllers/api/pj1/clients_controller.rb
index 78ac0a1..9b60278 100644
--- a/app/controllers/api/pj1/clients_controller.rb
+++ b/app/controllers/api/pj1/clients_controller.rb
@@ -1,5 +1,5 @@
class Api::Pj1::ClientsController < ApiController
- before_action :set_client, only: [:show, :update, :destroy]
+ before_action :set_client, only: [:show, :update]
#例外処理
rescue_from Exception, with: :render_status_500
このように、指定したコミットで行っていた内容が全て削除されていることがわかります。
エディタを立ち上げない方法
git revertでエディタを立ち上げない方法
わざわざエディタを起動したくない場合は、「–no-edit」オプションを使うことでデフォルトで設定されるコミットメッセージの冒頭に「Revert」がついたコミットメッセージを採用することができます。
git revert --no-edit
実例
例えば以下のようなコミットログがあるとします。
$ git log --oneline
0701d9d (HEAD -> test, second/aa, origin/aa, aa) [U]docker-compose add webpack port 3035
a90d4ef [U]content-security-policy(CSP) enable webpack-dev-server
6adca49 [A]destroyメソッド & Modal追加
この中で、3つ目のコミット「6adca49」の内容を取り消し、かつエディタを起動しない場合は以下のようにします。
$ git revert 6adca49 --no-edit
Removing app/javascript/components/Modal.vue
[test 2d9d637] Revert "[A]destroyメソッド & Modal追加"
Date: Thu Jan 27 19:05:07 2022 +0900
4 files changed, 4 insertions(+), 154 deletions(-)
delete mode 100644 app/javascript/components/Modal.vue
コミット履歴を確認します。
$ git log --oneline
2d9d637 (HEAD -> test) Revert "[A]destroyメソッド & Modal追加"
0701d9d (second/aa, origin/aa, aa) [U]docker-compose add webpack port 3035
a90d4ef [U]content-security-policy(CSP) enable webpack-dev-server
6adca49 [A]destroyメソッド & Modal追加
指定した「6adca49」を打ち消したコミットとして新たに「2d9d637」が最新のコミットになっていることがわかります。
コミットメッセージもデフォルトの「Revert “[A]destroyメソッド & Modal追加”」となっています。
実行内容の詳細はgit show <コミット番号>
で確認できます。
$ git show 2d9d637
commit 2d9d6370b4e8b805c12dc3b6d11b6bdf7b3e984b (HEAD -> test)
Author: author <example@gmail.com>
Date: Thu Jan 27 18:55:10 2022 +0900
Revertで"[A]destroyメソッド & Modal追加"を打ち消しました。
This reverts commit 6adca498b4dbdc4df8c18fe15a713507b80222d6.
diff --git a/app/controllers/api/pj1/clients_controller.rb b/app/controllers/api/pj1/clients_controller.rb
index 78ac0a1..9b60278 100644
--- a/app/controllers/api/pj1/clients_controller.rb
+++ b/app/controllers/api/pj1/clients_controller.rb
@@ -1,5 +1,5 @@
class Api::Pj1::ClientsController < ApiController
- before_action :set_client, only: [:show, :update, :destroy]
+ before_action :set_client, only: [:show, :update]
#例外処理
rescue_from Exception, with: :render_status_500
このように、指定したコミットで行っていた内容が全て削除されていることがわかります。
注意点:現在編集中のファイルはrevertできない
なお、現在編集していてるファイルがある場合はgit revertできません。
ステージ前(git add前)のファイルがある場合に表示されるエラー
$ git revert 6adca49
error: Your local changes to the following files would be overwritten by merge:
app/controllers/api/pj1/clients_controller.rb
Please commit your changes or stash them before you merge.
Aborting
fatal: revert failed
git add & git commitでコミットするか、git stashで一時的に変更を隠すかのどちらかをする必要があります。
ステージ後(コミット前)のファイルがある場合に表示されるエラー
$ git revert 6adca49
error: your local changes would be overwritten by revert.
hint: commit your changes or stash them to proceed.
fatal: revert failed
git commitでコミットするか、git stashで一時的に変更を隠すかのどちらかをする必要があります。
conflictの発生要因と対処法
現在のコミットと指定したコミットで同じ個所を修正している場合、コンフリクト(conflict)が発生します。
コンフリクトの発生例
$ git revert @@{12} --no-edit
Auto-merging style.css
CONFLICT (content): Merge conflict in style.css
error: could not revert 9390048... add line3
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
対処法
主な対処法は以下の2つです。
- –abortオプションを使う。
- 手動で修正してコミットする。
–abortオプションを使う
git revert --abort
を実行するとgit revertの処理自体をキャンセルしなかったことにできます。これで、revertコマンドを実行していない状態に戻ります。
手動で修正してコミットする
もう一つはエディタを開いて、手動で内容を修正してコミットする方法です。
#conflictが発生しているファイルを確認する
$ git st
On branch ft2
You are currently reverting commit 2767830.
(fix conflicts and run "git revert --continue")
(use "git revert --skip" to skip this patch)
(use "git revert --abort" to cancel the revert operation)
Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: style.css
#vimエディタで修正する
vi style.css
#add & commit
git add <対象ファイル> && git commit -m "メッセージ"
マージ(merge)したコミットを打ち消す方法
コマンド
-mオプションを使うとgit mergeしてあるコミットを打ち消すこともできます。
その際は、現在いるブランチかトピックブランチのどちらのコミットを採用するかを、1か2の番号で指定する必要があります。
git revert -m <パターン番号> <マージコミット>
なお、「-m」オプションは「–mainline」のショートオプションです。
パターン番号は1と2の二つです。
- 1: 現在のブランチ
- 2: 派生しているブランチ
マージコミット打ち消しの処理の流れ
以下のようなコミット履歴がある場合、Hがマージコミットになります。
#コミット履歴(Hがマージコミット)
A---B---C
/ \
D---E---F---G---H
master
この状態でコミットHの作業を打ち消して、新しいコミットを作ることができます。
その際、採用するコミットをメインのブランチとする場合は-mオプションの引数で「1」を指定します。
$git revert -m 1 H
すると、コミット履歴は以下のようになります。
A---B---C
/ \
D---E---F---G---H---H'
master
パターン番号で「1」を指定しているので、新しく生成されたコミット「H’」の内容は「G」と同じになります。
なお、「2」を指定した場合は「C」と同じになります。
マージコミットをrevertする時の注意点
マージコミットをrevertした場合、revertしたブランチのコミット履歴はmerge済みの状態です。このため、git mergeしようとすると、「Already up-to-date.」と表示されます。
$ git merge topic
Already up-to-date.