【Git】取り消しコマンドを実行しようとしているあなたへ

## はじめに

Gitでやらかしたことはありますか？私はもちろんあります。まあ人間ミスするものなのでそれは仕方ないはず。本当に大事なのはミスをどう取り返すか、だと思います。
慌てて取り消しコマンドを調べて実行したが、思った動作にならず余計に手間が増えると地獄です（自戒）
よほど時間がない場合は別ですが、どう取り消すか分からないままコマンドを実行するのはなるべく避けたいところ。

そこで、今回は誤った箇所だけを取り消す方法を紹介します。
- 誤ってステージングしたのなら、ステージング前に戻す
- 誤ってコミットしたのなら、コミット前に戻す

といったように、取り消しするにしてもその範囲を最小限に留めることで他への影響を抑えます。
今回は下記のフェーズにおいて、一つ前のフェーズに戻るためのコマンドを紹介します。 

1. コード修正（ステージング前）
2. git add
3. git commit -m "commit message"
4. git push

pushに関しては1つ前のフェーズに戻る、ではなく1つ前のcommitに戻る、ことになりますがpushの取り消し方法としてはこれがおすすめなので許してください。

## ステージング前

ステージング前なのでシンプルにコードを修正しただけの状態です。  
`git status`で状態を確認してみましょう。  

```text
$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   home/components/common/Constant.js
        modified:   home/public/Gitlogo.png

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        home/git/git_cancellation/
        home/public/git/git_cancellation/

no changes added to commit (use "git add" and/or "git commit -a")
```

コミットしたければ`git add`してください、と言われていますね。  
この状態は、gitコマンドを使って何かしたわけではないので、基本的には修正箇所をCtrl+Zとかで戻せばそれでOKです。  
\
敢えてコマンドで実行するとすれば、下記のコマンドを使いましょう。  

```javascript
git checkout .
```

一応`git status`で状態を確認しておきましょう。  

```text
$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
```

変更内容が取り消されて、`working tree clean`となってますね。大丈夫そうです。

## git add後

`git add -A`などで変更をステージングした後です。  
とりあえず`git status`で状態を確認しましょう。  

```text
$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   home/components/common/Constant.js
        new file:   home/git/git_cancellation/Blog.jsx
        new file:   home/git/git_cancellation/index.html
        new file:   home/git/git_cancellation/index.jsx
        modified:   home/public/Gitlogo.png
        new file:   home/public/git/git_cancellation/blog-post-git-3.md
```

コミットの準備ができている状態です。  
\
ステージングを取り消すためには下記のコマンドを使いましょう。  

```javascript
git reset HEAD
```

再び`git status`を実行すると、ステージング前の状態に戻っているはずです。

## git commit後

`git commit -m "hogehoge"`でコミットした後です。この辺りでミスに気づくとなんとなく焦りが出てきます。ここでは`git log`コマンドで状態を見てみましょう。  

```text
$ git log
commit hogehogecommitid (HEAD -> main)
Author: mochimochimax
Date:   Fri Mar 22 22:19:55 2024 +0900

    commit test

commit fugafugacommitid (origin/main)
Author: mochimochimax
Date:   Thu Mar 21 21:45:49 2024 +0900

    git記事更新中
```

コミットログを見ると`hogehogecommitid`が最新のコミットとなっています。  
\
コミットを取り消すためには下記のコマンドを使いましょう。  

```javascript
git reset --soft HEAD^    // Linuxのターミナルの場合はこれで
git reset --soft "HEAD^"  // コマンドプロンプトでは^は特殊文字なので""で囲みましょう
```

このコマンドはあくまで<font color="red">**コミットだけを取り消す**</font>ため、ステージングされた状態に戻り、ローカルの変更は保持されます。
実行後、`git log`で状態を確認すると、最新のcommit IDは一つ前の`fugafugacommitid`となっていることが確認できます。  

```text
$ git log
commit fugafugacommitid (origin/main)
Author: mochimochimax
Date:   Thu Mar 21 21:45:49 2024 +0900

    git記事更新中
```

## git push後

`git push`でリモートに反映した後です。これは焦る。
まずは`git log`で状態を確認しましょう。  

```text
$ git log
commit hogehogecommitid (HEAD -> main)
Author: mochimochimax
Date:   Fri Mar 22 22:19:55 2024 +0900

    miss commit

commit fugafugacommitid (origin/main)
Author: mochimochimax
Date:   Thu Mar 21 21:45:49 2024 +0900

    fuga commit

commit hogefugacommitid (origin/main)
Author: mochimochimax
Date:   Thu Mar 21 20:45:49 2024 +0900

    hoge commit
```

最新のコミットである`hogehogecommitid`はコミットメッセージがmiss commitとなってますね。このコミットを取り消しましょう。
取り消す方法は色々ありますが、下記のコマンドで取り消すことをおすすめします。  
※厳密には<font color="red">"取り消し"</font>ではなく<font color="red">"打ち消し"</font>ですが、ここでは"取り消す"と表現しています。  

```javascript
git revert HEAD  // このコマンドを実行してもcommitまでしかされないので
git push         // git pushの実行が必要
```

`git revert HEAD`は直前のpushを取り消す内容のコミットを作成するコマンドです。
変更履歴を残すので、ミスはバレますが安全な方法なのでrevertが良いと思います。  
<font color="red">※コマンド実行後に謎の編集画面みたいなのが出てきますが、vimと同じく`:wq`を入力すれば次へ進めます。</font>  
\
両コマンド実行後に再び`git log`で確認してみましょう。  

```text
$ git log
commit rlatestcommitid (HEAD -> main, origin/main)
Author: mochimochimax
Date:   Mon Mar 25 21:38:03 2024 +0900

    Revert "miss commit"

    This reverts commit hogehogecommitid.

commit hogehogecommitid (HEAD -> main)
Author: mochimochimax
Date:   Fri Mar 22 22:19:55 2024 +0900

    miss commit

commit fugafugacommitid (origin/main)
Author: mochimochimax
Date:   Thu Mar 21 21:45:49 2024 +0900

    fuga commit
```

取り消したいコミットの`hogehogecommitid`がRevertされていることが確認できます。
内容的には一つ前の`fugafugacommitid`に戻っているはずです。

## さいごに

今回はGitの各フェーズにおける操作の取り消し方法について紹介しました。
普段の作業中はあまり必要ありませんが、人はいずれミスするもの。
コマンドを覚える必要はありませんが、ミスっても何とかなると知っておいてくださいね。  
\
[webサイト](https://mochinochikimchi.com/)公開してますので、良かったら見ていってください！
[ハンドメイド](https://jp.mercari.com/user/profile/218655300?utm_source=ios&utm_medium=share)、[LINEスタンプ](https://store.line.me/stickershop/product/25451213/ja?utm_source=gnsh_stickerDetail)、[アプリ](https://play.google.com/store/apps/details?id=com.teamdelta.mealmotion)もあります！