【git】git stash の使い方を具体例を使ってわかりやすくしてみた

 
## はじめに
Git Hubを使用するときに、次のようなことありませんか。

- プルリクして他の人に確認をしてもらっている時にそのプルリクの内容を使用して開発を続けたい。
 
- 作業するブランチを間違えて本来作業したいブランチにその作業した内容を反映させたい。

そんなときに**stash**というコマンドが便利のなので使用例と共に紹介していこうと思います。
git初心者のためもっと便利な方法がありましたら指摘してただけると幸いです。

## 前提として
- git hub の基本的な使い方（comit,push,pullなど）が分かっていること

## 私の使用している環境
- pc:macOS Catalina 10.15.7
- 統合開発環境：atom　version1.50.0

## stashについて
**stash**とは・・・
一言で言うとコミットからの変更履歴を**stash list**に避難（保持）ができるコマンドです。

具体例を使用して説明していきます。

大まかな手順をまとめておきます。

- 手順①Aブランチをつくってtest1.pyプルリクエスト
- 手順②プルリクエスト後Aブランチのままtest1.pyに内容を追加
- 手順③test1.pyに追加した内容をgit stash listに避難させる
- 手順④**git stash list** でstashした内容の確認
- 手順⑤新しいブランチを作成（Bブランチ作成）
- 手順⑥リモートの内容をBブランチにpullする（Aブランチの状態によってpullしてくる箇所が異なる）
- 手順⑦git stash listの内容を反映することができるコマンドを確認
- 手順⑧git stash listの内容を反映する


### 手順①Aブランチをつくってtest1.pyプルリクエスト
masterブランチからAブランチを作成後、以下のファイルをコミットしてプルリクエストをした。

```:test1.py
# 最初のコミット
print("test1")
```

次にプルリクエストを待っている間にコミットしたファイルを使用したい。

### 手順②プルリクエスト後Aブランチのままtest1.pyに内容を追加
Aブランチのままtest1.pyに以下の内容を追加した。

```:test1.py
# 最初のコミット
print("test1")

# 内容の追加
print("test2")
```
保存をすると画像みたいにunstagedの箇所にtest1.pyの変更が反映される。

<img width="243" alt="スクリーンショット 2020-10-15 21 53 31" src="https://user-images.githubusercontent.com/57455167/96156441-07ef8180-0f4c-11eb-9d1a-6bf16c2f5797.png">



次にこの追加した内容を違うブランチに反映したい。
同じブランチでそのままコミットすることも可能ですが、基本的に相手に確認してもらっている最中にコミットするのはあまり気持ちのいいものではないので避けたい。今回の例は追加のみでしたが実際は手順①でプルリクしている箇所の間違いに気づいて修正することも考えられます。（相手からすると途中までみてたのに勝手に内容変えられると最初から見ないといけないじゃないかクソが！となってしまします。笑）
　
### 手順③test1.pyに追加した内容をgit stash listに避難させる
変更内容を避難させる。
ターミナル（windowsの場合はコマンドプロンプト）にて`git stash`コマンドを実行します。するとAブランチにあるtest1.pyファイルは以下のようになります。

```:ターミナル
git stash

```
<実行後>


```:test1.py
# 最初のコミット
print("test1")
```

手順①でコミットした時のファイルの内容に戻ります。言い方を変えると手順②で追加した内容を`git stash list`に避難させています。unstagedの箇所にあったtest1.pyの変更もなくなります。（以下の画像のようになります。）

<img width="244" alt="スクリーンショット 2020-10-15 22 08 48" src="https://user-images.githubusercontent.com/57455167/96156401-fc9c5600-0f4b-11eb-967a-e15140bc2b87.png">


### 手順④git stash list を確認するコマンドの確認
避難させたgit stash listを確認する。使用するコマンドは以下のとおりです。

###### ①

```
git stash list
```

（内容）
git stash listを確認できます。
（使用例）

```:ターミナル
git stash list

<以下実行結果>
stash@{0}: WIP on branch_name: commit_id2 commit_comment2
```

上の`stash@{0}`に先ほど避難させた内容が入っています。この0はstash listの0番目だよってことを示しています。複数ある場合はこの数字によって使用したいstash listを指定します。実行しても何も起きない場合はgit stash list がないことを示します。
※git stash listにsatsh@{0}があるときにgit stash listコマンドを実行すると実行前のstash@{0}はstash@{1}となる。新たにstashされた内容がstash@{0}となる。{}の中の数字が小さいほど新しいstash listの内容である。

###### ②

```
git stash show stash@{0} -p
```

（内容）
git stash list の退避内容が確認できます。stash@{0}の中の0はgit stash list が複数ある際にどのstash listを確認したいかを指定するものです。`-p`の部分は`--patch`でも代用可能です。

（使用例）

```diff:ターミナル
git stash show stash@{0} -p

<以下実行結果>
# 最初のコミット
print("test1")
+
+# 内容の追加
+print("test2")

```

###### ③

```
git diff stash@{0}
```

（内容）git stash list のdiff(差分)を表示できます。言葉での説明はわかりにくいので使用例をみてください。

（使用例）

```diff:ターミナル
git diff stash@{0}

<以下実行結果>
# 最初のコミット
print("test1")
-
-# 内容の追加
-print("test2")
```


### 手順⑤新しいブランチを作成（Bブランチ作成）
反映をさせる前に新しいブランチを作ります。ここではmasterブランチからBブランチを作ります。

### 手順⑥リモートの内容をBブランチにpullする（Aブランチの状態によってpullしてくる箇所が異なる）
Bブランチ作成後に、リモートの内容をpullするのですが、Aブランチのプルリクがマージされているのか、されていないのかでpullしてくる箇所が変わってきます。

1.マージされている場合

`git pull origin master`によりリモートのmasterブランチの内容をBブランチに反映させる。その時のtest1.pyの内容は以下のとおりである。

```:test1.py
# 最初のコミット
print("test1")
```

2.マージされていない場合
`git pull origin A`によりプルリク中のAブランチの内容を反映させる。これでもtest1.pyのAブランチの内容をBブランチに反映させることができる。反映内容は上記と同様。

```:test1.py
# 最初のコミット
print("test1")
```

※注意

２の方法により**pullしてきた箇所**を修正すると、AブランチのプルリクがマージされたあとBブランチのプルリクをマージしようとするとコンフリクトしてしまいます。コンフリクトしても都度解消すれば特に問題はありません。
pullしてきた箇所を修正せず追加のみだとコンフリクトはおきません。

（補足）Aブランチの内容をBブランチにpullしたいときにAブランチに複数のコミットがあり、その中の１つの内容を反映させたい場合があると思います。その時は`git cherry-pick`という便利なコマンドがあります。cherry-pickについて知りたい方は以下のurlでわかりやすく説明されている方がおられますのでそちらを参考にしてください。

[[git]他ブランチの作業を自分のブランチに持ってくる方法まとめ](https://qiita.com/tommy_aka_jps/items/07cce1f1759cdc0c1e3c)

### 手順⑦git stash listの内容を反映することができるコマンドを確認
反映ができるコマンドは主に２つあります。

○1つ目

```
git stash apply stash@{0}
```


こっちは反映した後にgit stash listはそのまま残ります。

○２つ目

```
git stash pop stash@{0}
```

こっちは反映した後にgit stash list を削除されます。

{}の中の数字は整数を入れてどのstash listの内容を反映するのかを指定します。
stash listを指定しない場合は、デフォルトでstash@{0}指定されます。


### 手順⑧git stash listの内容を反映する
手順⑦で確認した`git stash pop`コマンドにより避難させた内容を以下のとおり反映します。

```:ターミナル
git stash pop stash@{0}

```


実行後のtest1.pyファイル

```:test1.py
# 最初のコミット
print("test1")

# 内容の追加
print("test2")
```

これで手順①でプルリク後からの変更内容をBブランチに反映することができました。
このあとに`git stash list`を実行してもstash@{0}はありません。`git stash apply stash@{0}`により実行した場合だとstash@{0}は残っています。


##参照url

- [マージコンフリクトについて(GitHub公式)](https://docs.github.com/ja/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-merge-conflicts)

- [【Git】stashした内容をdiff表示する
](https://qiita.com/hashimotoryoh/items/ef764aa05d405afb6f61)