間違えてcommit、addした時の操作 [Git]

こんにちは!もとひろです。
今日は、Gitで間違えてcommitやaddをしてしまった際に行う操作をまとめたいと思います。
できればお世話にならずにいきたいコマンドではありますが、使い方を知っていないといざという時困ってしまうので、まとめました。



まず、巻き戻す操作の基本であるresetについてまとめます。

resetの基本

resetコマンドの処理の流れは3段階あります。

  1. HEAD(最新のコミット)を指定したコミットまで移動する

  2. インデックスを巻き戻す(取り消す)

  3. 作業ディレクトリを巻き戻す(取り消す)


オプションによってresetの処理をどこまで行うか指定することができます。

  • --soft:1を行う
     HEADの移動のみ

  • オプションなし or --mixed:1と2を行う
     HEADの移動、インデックスを巻き戻す

  • --hard:1、2、3を行う
     HEADの移動、インデックスと作業ディレクトリを巻き戻す

※ 重要な注意点 ※

resetの処理の3つ目にある「作業ディレクトリの巻き戻し」、つまりgit reset --hardを実行する際は、十分注意する必要があります!
なぜなら、作業ディレクトリで変更したファイルが変更前の状態に上書きされてしまうからです。
自分が一生懸命実装したコードも、コミットしていなければ警告など出ることなく一瞬で消え去ります。
コミットされている内容は後から取り戻すことができますが、コミットされていない内容は取り戻すことができません

HEADについて

HEADとは、「現在のブランチの最新コミット」のことを指します。
HEAD~は「現在のブランチの最新から1つ前のコミット」を指します。
~2のように~の数によって、履歴を何個遡るかを表します。
(コマンドのcommit以外のHEADの動きも履歴1つ分にあたります)

また、HEAD@は同じで、~^は同じです。
ややこしいですが、HEAD~=HEAD^=@~=@^となります。

実際の使用例

ここからは、実際に使うであろうシチュエーションごとに例をあげていきます。
reset以外のコマンドもシチュエーションに合わせて記載してあります。

例1:直前のコミットに対して

コミットを取り消してインデックスに戻す

  • git reset --soft HEAD~

コミットもインデックスも取り消して作業ディレクトリに戻す

  • git reset HEAD~

コミットメッセージの修正

  • インデックスが空の状態でgit commit --amend

コミットにファイルを追加したい

  • HEADを操作していない状態で、git add 追加ファイル名git commit --amend


例2:コミットは関係なくそのままで

インデックスを取り消して作業ディレクトリに戻す

  • git reset (HEAD) ファイル名

  • git restore --staged ファイル名

作業ディレクトリの変更したファイルを変更前の状態に戻す

  • git restore ファイル名

  • git checkout ファイル名

作業ディレクトリの変更したファイルを 全部まとめて 変更前の状態に戻す(要注意)

  • git restore .

  • git checkout .

  • git reset --hard (HEAD)

例3:結構前のコミットの状態に戻す

  • git reset (--soft) コミットハッシュかHEAD@{数字}
     --softをつけるかは一緒にインデックスを取り消すかどうかで決めます。
     --hardもオプションとしては可能ですが、何度も言うように要注意です。


補足:コミットハッシュとHEAD@{数字}

git reflogでHEADの移動履歴をみることができます。
(commitだけでなくcheckout,marge,pull,fetch,reset,revert,rebaseなどのコマンドの履歴も保存されています)
履歴にあるHEAD@{数字}は、HEADからどのくらい前の履歴なのかを示しています。
例:HEAD@{2} HEADから2つ前の履歴
そのためHEAD@{数字}は変動するので、かなり前のコミット状態に戻す際などは「コミットハッシュ」を直接入力したほうが操作を間違えなくて良いと思います。
(私は何回も間違えました)

まとめ

今回はGitで間違えてcommitやaddをしてしまった際に行う操作をまとめました。
まとめてみて思ったことは、極力使わずに進めていけたら良いなぁ…ということでした!
間違い等ありましたら、ぜひコメントで教えていただけたら幸いです。

参考リンク

Git - 作業のやり直し
Git - リセットコマンド詳説

おまけの話

今回Gitについて取り上げた理由を書いていこうと思います。
先日の輪読会で、初めてドライバーを経験しました!(ドライバーはランダムで担当します)
みんなでGitHubで共有しているファイルを使い、コードを入力したりして書籍を学んでいるのですが、いざドライバーやり始めたらgit pull origin mainできない!😵
なぜかわからずおろおろしてしまいました…
結局理由は、自分で予習復習をした際にmainブランチでいろいろファイルを変更してしまったからでした。
そのとき教えていただいたのが、色々変更してしまったたくさんのファイルを無きものにするgit reset --hardでした。
自分でファイルをいじる際はブランチをちゃんと作成して行うという基本を絶対に忘れないようにしようと心に誓い、あまり知らなかったgit resetについて調べた次第です。

とても良い勉強になりました!
終わります👋