git revert は元に戻すコマンドの一種だと考えることもできます。ただし、通常の元に戻す操作とは異なる動作をします。プロジェクト履歴において、そのコミットがなかったことにするのではなく、そのコミットによって加えられた変更を打ち消し、その結果を含む新しいコミットを追加します。これは Git の履歴を保全するためであり、バージョン履歴の完全性の維持とコラボレーションの信頼性の確保のために重要です。

「revert (打消し)」は、プロジェクト履歴からコミットを打ち消す場合に使用します。これは、バグの追跡を行った結果あるひとつのコミットが原因であることが判明した場合などに有用なコマンドです。git revert を使用することにより、手作業で分析、修正し、その結果を新しいスナップショットとしてコミットするのではなく、それらすべてを自動的に行うことができます。

git revert - アトラシアンの Git チュートリアル

仕組み

git revert コマンドを使うと、リポジトリのコミット履歴への変更を元に戻すことができます。git checkoutgit reset など、元に戻す他のコマンドでは HEAD とブランチ ref ポインターが指定したコミットに移動します。Git revert でも指定したコミットを取得することができますが、git revert では ref ポインターは指定したコミットに移動しません。打消し操作では指定したコミットを取得し、取得したコミットの変更を打ち消して新しい「打消しコミット」を作成します。その後、ref ポインターは新しい打消しコミットをポイントするよう更新され、ブランチにもその情報が伝わります。

以下のコマンドラインを使ってサンプルリポジトリを実際に作成してみましょう。

$ mkdir git_revert_test
$ cd git_revert_test/
$ git init .
Initialized empty Git repository in /git_revert_test/.git/
$ touch demo_file
$ git add demo_file
$ git commit -am"initial commit"
[master (root-commit) 299b15f] initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 demo_file
$ echo "initial content" >> demo_file
$ git commit -am"add new content to demo file"
[master 3602d88] add new content to demo file
n 1 file changed, 1 insertion(+)
$ echo "prepended line content" >> demo_file
$ git commit -am"prepend content to demo file"
[master 86bb32e] prepend content to demo file
1 file changed, 1 insertion(+)
$ git log --oneline
86bb32e prepend content to demo file
3602d88 add new content to demo file
299b15f initial commit

ここでは git_revert_test という新しく作成したディレクトリにリポジトリを作成して初期化しています。リポジトリに 3 つのコミットを作成し、そこにファイル demo_file を追加し、ファイルのコンテンツを 2 回変更しました。リポジトリの設定手順の最後に git log を呼び出し、コミット履歴を表示して 3 つのコミットすべてを表示します。この状態のリポジトリで git revert. を実行する準備ができました。

$ git revert HEAD
[master b9cd081] Revert "prepend content to demo file"
1 file changed, 1 deletion(-)

Git revert はコミット ref が渡されていることを要求し、ref がなければ実行しません。ここでは HEAD ref を渡しています。これにより直前のコミットを打ち消します。これは、コミット 3602d8815dbfa78cd37cd4d189552764b5e96c58 を打ち消す動作と同じです。打消しではマージと同様に、新しいコミットを作成すると、新しいコミットメッセージを求める新構成済みのシステムエディターが起動します。コミットメッセージを入力すると、保存した Git が動作を再開します。これで git log を使用してリポジトリの状態を調べ、以前のログに新しいコミットが追加されていることを確認できます。

$ git log --oneline
1061e79 Revert "prepend content to demo file"
86bb32e prepend content to demo file
3602d88 add new content to demo file
299b15f initial commit

ここで、3 番目のコミットは打ち消し操作後もプロジェクト履歴に残っていることに留意してください。変更を元に戻すためにそれを削除するのではなく、git revert によって新しいコミットを追加します。その結果として 2 番目と 4 番目のコミット後のリポジトリは全く同一の状態となり、なおかつ 3 番目のコミットは履歴に残っているため、その時点に戻ることも可能です。

よく使われるオプション

-e
--edit

デフォルトのオプションで、指定する必要はありません。このオプションを使うと構成済みのシステムエディターが開き、打消しをコミットする前にコミットメッセージを編集するよう求められます。

--no-edit

-e オプションを打ち消します。打ち消し操作ではエディターは開きません。

-n
--no-commit

このオプションを渡すと git revert を実行しても対象のコミットを打ち消す新しいコミットは作成されません。このオプションでは新しいコミットは作成されず、ステージングインデックスと作業ディレクトリに変更の打消しが追加されます。これらはリポジトリの状態を管理するために Git で使用するツリーの一種です。詳細については、「git reset」のページをご覧ください。

取消しと打消し

git revert は、1 つのコミットのみを元に戻すコマンドであることをしっかりと理解してください。そのコミットの後に行われたすべてのコミットを削除することによってプロジェクトを以前の状態に「戻す」コマンドではありません。Git では以前の状態に戻すコマンドは reset (取消し) であり、revert (打消し) ではありません。

git revert と git reset - アトラシアンの Git チュートリアル

打消しは、リセットと比較して 2 つの重要な利点があります。第一は、プロジェクト履歴の変更がなされない点です。そのため、すでに公開リポジトリに公開されているコミットに対しては「安全な」操作です。公開した変更履歴を改変することの危険性については、「git reset」のページをご覧ください。

第二は、git reset は現在のコミットから後戻りする働きをするのみであるのに対し、git revert では履歴における任意の時点での個々のコミットをターゲットにできるという点です。たとえば、git reset コマンドを使用して過去のひとつのコミットのみを元に戻そうとすると、ターゲットとしたコミットの後に行われたすべてのコミットを削除し、次にターゲットのコミットを削除し、その後でターゲットとしたコミットの後に行われたすべてのコミットを再コミットする必要があります。明らかにこれは効果的に元に戻す方法ではありません。git revert とその他の元に戻すコマンドの違いの詳細については、「リセット、チェックアウト、打消し」を参照してください。

概要

git revert コマンドは作業を前進させながら変更を安全に元に戻すことができる方法です。コミット履歴でコミットを削除したり隔離したりするのではなく、新しいコミットを作成して指定した変更を打ち消します。Git revert では git reset よりも作業内容を消失するリスクを軽減できます。git revert の効果を実証するために、git loggit commitgit reset の各コマンドを使用しました。これらのコマンドの詳細はそれぞれのページをご覧ください。

git revert を学ぶ準備はできていますか?

この対話式チュートリアルを利用しましょう。

今すぐ始める