gitのコミットを取り消して元に戻す方法まとめ

今回はgitのcommitを取り消して元に戻す方法を紹介します。

gitは基本的に全てのcommitを記録しているので、いつでも取り消して元に戻すことができます。

 

直前のcommitを取り消す

commitした後に間違いに気づいても、まだpushしていないなら取り消しが簡単なのですぐにcommitをやり直せます。

git reset <branch>は現在のブランチの先頭を指定のcommitに強制的にリセットするコマンドです。

「–soft」オプションを付けると、作業ツリーとインデックスをそのままの状態で、ブランチの先頭のみを変更できます。

git commitを直前に戻すには以下でできます。

git reset --soft HEAD^

 

–softを使えばcommitを取り消してもインデックスと作業ツリーはそのまま残ります。

なのでファイルを修正してもう一度commitをやり直すことができます。

逆にインデックスも作業ツリーも同時に取り消してしまいたいときは–hardオプションを使用します。

 

過去のcommitの直後に戻す

git reset に–hardオプションを付けるとHEAD、インデックス、作業ツリーの変更もすべて取り消してくれます。

これにより、一つ前のコミットを作成した直後に戻る事ができます。

git reset --hard HEAD^

 

注意点としては変更内容が全て消えるので、インデックスや作業ツリーに変更が残りません。

commitかstashしていない内容は元に戻すことができないので気をつけましょう。

 

commitを打ち消すcommitを作る

間違えてcommitしてしまった時に、それを打ち消すようなcommitを作成して打ち消すという方法です。打ち消しコミットと呼ぶこともあります。

打ち消しコミットはgit revertによって作成しましょう。

// 直前の変更を打ち消すコミットを作成 (2つは同義)
git revert 
git revert HEAD

 

このrevertによるコミットは単純に1つの新しいcommitなので過去のbranchに影響を与えることはありません。

そのため、pushしても衝突することはありません。

 

直前のcommitを上書き修正する

git commit に「–amend」オプションをつけて、直前のcommitを上書き修正する方法です。

実際は現在のHEADに上書きされています。

// 直前のコミットを修正する。
git commit --amend

 

過去のcommitを削除する

git rebaseで過去のブランチを修正する方法です。「i」は「interactive(インタラクティブ)」を意味してます。

例えば、下記のように取り消したいコミットの直前を指定します。

注意点は、あくまで「リベース」を実行していますので、取り消したいコミットではなく、リベースをかけるコミットを引数で指定するようにします。

// 現在のブランチを、<commit> までリベース。
git rebase -i <commit>

 

実行後は以下のようにテキストエディタで編集するためのファイルが立ち上がります。

pick 6fcde18 Replace the news link.
pick 460b0b8 Set public false for the news.
pick de9f1d2 Fix the bug .
pick 4b0346d Remove news.

# Rebase b4792e2..4b0346d onto b4792e2 (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

 

取り消し操作を間違えてしまった場合

「間違えてcommitした部分を直そうと思ったのに、直す操作を間違えてしまった。commitの履歴がもうよくわからなくなってしまった…」

そういった場合はgit reflogを使います。

git reflogはは、HEADを含む「参照」の移動をすべて記録しています。

これを元に過去の好きなタイミングに戻り、おかしくなってしまった部分を確認しましょう。

// いまのブランチのすべてのコミット歴史を表示
git reflog

 

HEAD{ }内には過去から何番目のHEADかが順番に書いてあります。

ここから元に戻したい場所を探し、git reset –hard で強制的に戻します。

// 指定のコミットに、ブランチ状態を強制上書き。全部取り消し。
git reset --hard HEAD@{3}

 

これで過去のある地点から作業が全てやり直せるので、途中で何がどうなっているのかわからなくなっても安心です。

 

pushの衝突を避ける

これらの方法でローカルの過去のブランチを書き直して、もし修正前をすでにpushしてしまっていると、修正後のpushが衝突してしまいます。

その場合、「-f」オプションを付けて push することで、強制的に上書きできます。

// 強制的にpushして、リモートの履歴を上書きする
git push -f origin <branch name>

 

ただし、他の人と共同でブランチを参照している場合はこれはやらないようにしてください。

他の人が次回のpushで全員衝突することになるので、面倒なことになります。

この方法は一人で開発している時だけ使うようにしましょう。

 

まとめ

gitのcommitを取り消す方法は色々ありますが、時と場合によって使い分けることができるとさらにいいですね。

間違いが発生してしまうのはある程度しょうがないことなので、間違えた時にいかにスムーズに対処できるかが重要です。

間違えても焦らずに落ち着いて対処するようにしましょう。