Git revert
git revert
は元に戻すコマンドの一種だと考えることもできます。ただし、通常の元に戻す操作とは異なる動作をします。プロジェクト履歴において、そのコミットがなかったことにするのではなく、そのコミットによって加えられた変更を打ち消し、その結果を含む新しいコミットを追加します。これは Git の履歴を保全するためであり、バージョン履歴の完全性の維持とコラボレーションの信頼性の確保のために重要です。
「revert (打消し)」は、プロジェクト履歴からコミットを打ち消す場合に使用します。これは、バグの追跡を行った結果あるひとつのコミットが原因であることが判明した場合などに有用なコマンドです。git revert
を使用することにより、手作業で分析、修正し、その結果を新しいスナップショットとしてコミットするのではなく、それらすべてを自動的に行うことができます。
仕組み
git revert
コマンドを使うと、リポジトリのコミット履歴への変更を元に戻せます。git checkout や git reset など、元に戻す他のコマンドでは、HEAD
とブランチ ref ポインターが指定したコミットに移動します。git revert
でも指定したコミットを取得できますが、git revert
では ref ポインターは指定したコミットに移動しません。revert(打ち消し)操作では指定したコミットを取得し、取得したコミットの変更を打ち消して新しい「打ち消しコミット」を作成します。その後、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"
[main (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"
[main 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"
[main 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 チートシート
ソリューションを見る
Bitbucket Cloud での Git の使用方法についてのチュートリアルです。
ここでは git_revert_test
という新しく作成したディレクトリにリポジトリを作成して初期化しています。リポジトリに 3 つのコミットを作成し、そこにファイル demo_file
を追加し、ファイルのコンテンツを 2 回変更しました。リポジトリの設定手順の最後に git log
を呼び出し、コミット履歴を表示して 3 つのコミットすべてを表示します。この状態のリポジトリで git revert.
を実行する準備ができました。
$ git revert HEAD
[main 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 (打消し) ではありません。
打ち消しは、リセットと比較して 2 つの重要な利点があります。第一は、プロジェクト履歴の変更がなされない点です。そのため、すでに公開リポジトリに公開されているコミットに対しては「安全な」操作です。公開した変更履歴を改変することの危険性については、「git reset」のページをご覧ください。
第二は、git reset
は現在のコミットから後戻りする働きをするのみであるのに対し、git revert
では履歴における任意の時点での個々のコミットをターゲットにできるという点です。たとえば、git reset
コマンドを使用して過去のひとつのコミットのみを元に戻そうとすると、ターゲットとしたコミットの後に行われたすべてのコミットを削除し、次にターゲットのコミットを削除し、その後でターゲットとしたコミットの後に行われたすべてのコミットを再コミットする必要があります。明らかにこれは効果的に元に戻す方法ではありません。git revert
とその他の元に戻すコマンドの違いの詳細については、「リセット、チェックアウト、打消し」を参照してください。
要約
git revert
コマンドは作業を前進させながら変更を安全に元に戻すことができる操作です。コミット履歴でコミットを削除したり隔離したりするのではなく、新しいコミットを作成して指定した変更を打ち消します。git revert
では git reset
よりも作業内容を消失するリスクを軽減できます。git revert
の効果を示すために、git log、git commit、git reset の各コマンドを使用しました。これらのコマンドの詳細はそれぞれのページをご覧ください。
この記事を共有する
次のトピック
おすすめコンテンツ
次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。