【Git】コミットを取り消して元に戻す方法

Git
記事内に商品プロモーションを含む場合があります。

Gitにコミット済みのファイルを取り消して元の状態に戻したいな。

コミット直後に修正箇所が見つかったり、過去のコミット履歴を取り消したいときがあると思います。

今回は、コミットを取り消すコマンドや使い方について詳しく解説します。

スポンサーリンク

コミットを取り消す2つのGitコマンド

コミットを取り消しするgitコマンドにはgit resetgit revertの2つがあります。

ざっくり説明すると、特徴は下記の通りです。

git reset
:HEADとブランチを指定のコミットに移動する
git revert
:指定したコミットを打ち消す

実感が湧かないと思うので、例を交えながら解説します。

スポンサーリンク

git resetでコミットを取り消しする方法

git resetHEADとブランチを指定しコミットに移動させるコマンドです。

どういう事か、例で見てみましょう。

git resetの仕組み

現在、mainブランチには「commit1」~「commit4」の4つのコミット履歴があるとします。

git logで見てみましょう。

現在HEADとmainブランチは最新の「commit4」を参照していることがわかります((HEAD -> main)と書かれた場所に注目)。

図で書くとこうですね。

右に行くほど、新しいコミットです。

たとえば「commit3と4を取り消してcommit2に戻したい」という場合、git resetを使うと下図のようにHEADとmainブランチをcommit2に移動させることができます

commit3とcommit4は参照不可の状態になるため、実質的にcommit2が最新のコミットとなります

なお、commit3とcommit4は暫くしてから自動的に削除されます。

git resetの使い方

git resetの基本的な使い方を解説します。

直前のコミットに戻りたい場合

直前のコミットに戻りたい場合は、「HEAD^」と指定すればOKです。

$ git reset HEAD^

上記コマンドを実行すると、HEADとmainが直前のコミットに戻ります。

先ほどの例だと「commit3に移動」ですね。

実質上commit4が取り消され、commit3が最新のコミットとなります。

git logコマンドで確認してみましょう。

HEADとmainブランチがcommit3を参照しているのがわかります。

同時に、履歴からcommit4が消えているのも確認できますね。

なお、commit4は実際に消えているのではなく、現時点では「見えていない」だけです。

暫くした後に自動削除されますが、それまではいつでも戻すことができます(方法については後述します)。

ちなみに、「HEAD^^」と書くと2つ前のコミットに、「HEAD^^^」と書くと3つ前のコミットに戻せます。

コミット番号を指定して戻したい場合

特定のコミットを指定して戻すも可能です。

$ git reset [戻りたいコミットのSHA-1値]

たとえば、下記の「commit2」に戻りたいしましょう。

その場合はcommit2の「SHA-1値」を指定します。SHA-1値とは、簡単に言えば「コミットのID」です。

ちなみに、全部書く必要はなくて、冒頭の4~5桁でOKです。

$ git reset bcdf0

再度git logで確認すると、HEADとmainブランチがcommit2に移動していることがわかります。

ついでに、commit3とcommit4が消えているのも確認できますね。

先述のとおり、取り消し直後であればcommit3やcommit4に戻すことが可能です。

たとえば「戻すのはcommt2じゃなくてcommit3だった!」という場合でも、再度git resetでcommit3のSHA-1値を指定すれば大丈夫です。

$ git reset 532f7 [commit3のSHA-1値]

無事にcommit3に戻れます。

git resetのオプション

git resetはHEADとブランチを指定のコミットに移動させるコマンドですが、3つのオプションが用意されています。

それが、softmixed、そしてhardです。

git reset --soft
:コミット前の状態に戻す(リセット度:弱)
git reset --mixed(git resetと同じ)
:ステージング前の状態に戻す(リセット度:中)
git reset --hard
:ワーキングスペースも元に戻す(リセット度:強)

git reset --soft

softオプションは、3つの中でもっとも弱いリセットです。

下記コマンドを実行すると、直前のコミットだけを取り消してステージングエリアに戻します。

$ git reset --soft HEAD^

図がわかりやすいかもですね。

git reset --mixed(git reset)

mixedオプションは中程度のリセットになります。

下記コマンドを実行すると、直前のコミットとステージングが取り消されます

なお、git reset HEAD^のようにオプションを指定しない場合は、mixedオプションを指定したとみなされます。

$ git reset --mixed HEAD^

git reset --hard

hardオプションは、git resetの中でもっとも強力です。

下記コマンドを実行すると、コミットやステージングだけでなく、ワークツリーの変更内容もすべて「無かったこと」になります

$ git reset --hard HEAD^

ファイルの変更内容まですべて消えてしまうので、取扱いに注意が必要です。

スポンサーリンク

git revertでコミットを取り消しする方法

git revertは指定したコミットを打ち消すコマンドです。

git revertの仕組み

たとえば、下記のようなコミット履歴があって、「commit4を取り消したい」とします。

git revertを実行すると、commit4を打ち消すコミットが追加され、実質的にcommit3の状態に戻ります。

git revertの使い方

git revertは、取り消したいコミットのSHA-1(コミットのID)を指定します。

$ git revert [取り消したいコミットのSHA-1]

最新のコミット(HEAD)を取り消したい場合は、下のように書きます。

$ git revert HEAD

実際にやってみましょう。

先ほどと同じく、commit1~commit4の4つのコミットがあるとします。

たとえば「commit4を取り消したい」と思ったら、commit4のSHA-1値(コミットID)を指定します。

$ git revert 110339

なお、commit4は最新のコミットなので、下記コマンドでもOKです。

$ git revert HEAD

上記コマンドを実行するとエディタが開き、コミットメッセージを入力するよう求められます。

コミットメッセージは自由ですが、わかりやすい方がいいので「commit4の取り消し」としました。

入力後、エディタを閉じるとコミットが完了します。

git logでコミット履歴を確認してみましょう。

「commit4の取り消し」という、打ち消しのコミットが反映されていますね。

念のため、git diffコマンドで差分を確認すると、commit4の内容が削除され、commit3に戻っているのがわかります。

スポンサーリンク

git resetとgit revertどちらがおすすめ?

コミットの取り消しは、基本的にgit revertを使うのがおすすめです。

git revertがおすすめな理由

理由は上記の通りで、git revertは取り消す前のコミットも履歴に残るからです。

git resetは取り消しのコミット履歴が残らない

一方、git resetはコミットを取り消すと履歴も削除されるという特徴があります。

下記はgit resetを実行した際の挙動ですが、取り消したcommit4には実質上アクセスできない状態となり、いずれ消えてしまいます

「不要なんだし、消えても問題ないじゃん」と思うかもしれません。

確かに個人開発ならOKかもですが、共同開発で安易にコミット履歴を削除してしまうと、他の開発者のコミット履歴にも影響を及ぼす危険があります。

ですので、特に複数人で共同作業を行う際には、コミット履歴を削除するのは避ける方がベターです。

スポンサーリンク

まとめ

最後に、コミットを取り消すコマンドをまとめます。

git reset
:HEADとブランチを指定のコミットに移動する
:soft、mixed、hardの3つのオプションがある
:コミット履歴も消えるので注意が必要
git revert
:指定したコミットを打ち消す
:コミット履歴が残るのでおすすめ

コミットの取り消しは、実務でも結構使うので、この機会に整理しておきましょう。