resetやcheckoutじゃなくてrestoreを使おう![Git,Github]

# git restoreコマンドとは?

restoreコマンドとは、前回のコミット時点まで特定のファイルを復元するコマンドです。

今の状態から直前のコミットの状態までプロジェクトの状態をリセットしたいという時に便利なコマンドです。

## 特定のファイルに状態を戻す
特定のファイルの変更を元に戻したい、リセットしたいなと思った時に使用することができます。

ステージングしていない特定のファイルを元に戻すことができます。
```zsh
On branch <branch>
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:   <file_name>
```

この状態で下のコマンドを使用します。
```zsh:git
git restore <file_name>
```

そうすると下のようにファイルの変更がない前回のコミット状態に戻ります。

```zsh:zsh
On branch <branch>
nothing to commit, working tree clean
```

## 全てのファイルの状態を戻す
ファイルを`.`と指定することで全てのファイルの状態を前回のコミット状態に復元することができます。

```zsh:git
git restore .
```

しかし、restoreはステージングしている内容をリセットするのはできません。
ステージングしているのをステージング前に引き下げるのは、--stagedを使用します。
下のようにステージングしているファイルがあったとします。
```zsh:git
On branch <branch>
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   <file_name>
```

これを引き下げるために下のコマンドを使用します。
```zsh:git
git restore --staged <file_name>
```

そうするとステージング前の状態になります。

```zsh:git
On branch <branch>
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:   <file_name>
```

# resetコマンドとは?

resetは特定のコミット履歴までプロジェクト全体の状態を戻すことができます。

resetには3つのオプションがあります。

|オプション|効果
|---|---
|--soft|HEADの位置を戻す
|--mixed|HEADの位置・インデックスも戻す
|--hard|HEADの位置・インデックス・ワーキングツリーを戻す

:::note
### ワーキングツリーとは
最新のファイル状態のことを指します。
ここにあるファイルは、ステージングされていない変更・追加されたファイルを指すことになります。

### インデックス
ステージのことを指します。
addコマンドでステージングされたファイルが置いてる場所のことを指します。

### HEAD
最新のコミットの状態を指します。

:::

## --soft
--softを使うことで特定のコミットIDまでコミットの状態を戻すことができます。
```zsh:git
git reset --sof <commit_id>
```

例えばHEAD^を指定するとひとつ前のHEADの状態に戻ります。

```zsh:git
git reset --soft HEAD^
```

こうすると直前のコミットが取り消され、その際にコミットしたファイルがステージングされた状態になります。

:::note
### HEADとHEAD^の違い
HEADは現在の最新コミットを指します。
HEAD^は最新コミットの一つ前を指します。

なので--softでHEADを指定しても何も起きません。
:::

:::note
### コミットIDを指定しないとどうなるのか
コミットIDを指定しないとHEADと認識されます。
:::

## --mixed
--mixedを使うことでインデックスとHEADを特定のコミットIDまで戻すことができます。
```zsh:git
git reset --mixed <commit_id>
```

HEADを指定すると、ファイルをステージングしていない状態に戻ります。
```zsh:git
git reset --mixed HEAD
```

HEAD^を指定するとひとつ前のコミット状態まで戻しつつ、ステージングされていない状態に戻ります。(変更したファイルは残ります)
```zsh:git
git reset --mixed HEAD^
```



## --hard
--hardを使うことで、ワーキングツリーとインデックスとHEADが特定のコミットIDまで戻すことができます。
```zsh:git
git reset --hard <commit_id>
```

HEADを指定すると変更したファイルが無くなってしまいます。
```zsh:git
git reset --hard HEAD
```

HEAD^を指定すると直前のコミットを消してしまい、直前のコミットで作業した内容は全て消えてしまいます。
```zsh:git
git reset --hard HEAD^
```

# checkoutとは？
checkoutはブランチの変更やファイルの復元で使われてきたコマンドです。

- ブランチの切り替え
```zsh:git
git checkout <branch_name>
```
- ファイルの復元
```zsh:git
git checkout -- <file_name>
```

このコマンドは複数の機能を備えてるが故に初学者にとっては扱いづらく、加えて熟練者にとってもミスを引き起こしやすいものでした。

これらを分離して`switch`と`restore`コマンドが生まれました

# まとめ
上記で説明して分かる通り、resetとcheckoutはかなり複雑に機能が混在しており、ファイルの復元をしようとするとかなりミスを引き起こす可能性があることがわかると思います。

なのでできるだけresotreを使うことで、安全に最新のコミットした時の状態までファイルを復元させましょう。

|コマンド|機能
|---|---
|resotre|最新のコミットまでファイルを復元する
|reset|特定のコミット位置までプロジェクトを戻す
|checkout|ブランチの変更やファイルの復元
|switch|ブランチの変更

# git関連の記事

https://qiita.com/maooz4426/items/b547f8474e3a83f96336

https://qiita.com/maooz4426/items/0f994e08f17dfaa1b3ba

https://qiita.com/maooz4426/items/8ae2a7df1add39e9f943