git stash についてまとめてみた(file単位でstashしたい)

# この記事を書いたきっかけ

git stash をファイル単位で行いたい...

そんなわけで、ついでにGitマニュアルのStashページのまとめとかしてみました。
あまり使わないオプションもあるので、間違っていたらどなたか教えていただけると助かります。

# そもそも、stashって？

変更点を一時的に退避させるコマンドだと認識しています。
（マニュアルは汚れたディレクトリを隠すと記載しています）

# 基本的な使い方

だいたい、**変更した内容**を一時的に退避させるのに使います

```:例
// ステータス確認
C:\work\hoge>git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   nanikano_app/app/controllers/hogehoge_controller.rb

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

        nanikano_app/app/controllers/fugafuga_controller.rb
        
// stash 実施
C:\work\hoge>git stash
Saved working directory and index state WIP on master: d6816cb hogehoge
HEAD is now at d6816cb hogehoge

// 再度ステータス確認（退避済）
C:\work\hoge>git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        nanikano_app/app/controllers/fugafuga_controller.rb

// stashされているものを復元
C:\work\hogegit stash pop
Removing nanikano_app/app/controllers/hogehoge_controller.rb
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   nanikano_app/app/controllers/hogehoge_controller.rb

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

        nanikano_app/app/controllers/fugafuga_controller.rb

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (d4a0db5f1676baf0e208bhogea30832589e4hoge)


// ステータス確認
C:\work\hoge>git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   nanikano_app/app/controllers/hogehoge_controller.rb

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

        nanikano_app/app/controllers/fugafuga_controller.rb
```

と上記のように、Untracked fileは退避できない([オプション次第ではできる](#-u--include-untracked))
基本的にはstashで退避させてpopで退避させたものを復元するイメージ


# Git manualのシノプス

```
git stash list [<options>]
git stash show [<stash>]
git stash drop [-q|--quiet] [<stash>]
git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
git stash branch <branchname> [<stash>]
git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
	     [-u|--include-untracked] [-a|--all] [<message>]
git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
	     [-u|--include-untracked] [-a|--all] [-m|--message <message>]]
	     [--] [<pathspec>…​]]
git stash clear
git stash create [<message>]
git stash store [-m|--message <message>] [-q|--quiet] <commit>
```

## git stash list

今、stashしている物のリストを表示します。

```
stash@{0}: WIP on submit: 6ebd0e2... Merge branch 'dev'
stash@{1}: WIP on master: 9cc0589... Add work files
```
stash@{X}のXに当たる数字が低いほど新しいstashで、
onほにゃららの「ほにゃらら」に当たる部分が対象のブランチ
その後の7桁の文字列がコミットID
最後に記載されているのが、コミットメッセージになります。

## git stash show

stashした内容の詳細を表示してくれる

```
C:\work\hoge>git stash show
 .../app/controllers/hogehoge_controller.rb       |  14 --------------
 .../app/controllers/watashino_controller.rb      |   1 +
 2 files changed, 1 insertions(+), 14 deletions(-)
```

なお、バージョンを指定することでstashを選択することも可能（指定しない場合は最新の物の差分を表示）

```
C:\work\hoge>git stash show stash@{0}
 .../app/controllers/hogehoge_controller.rb       |  14 --------------
 .../app/controllers/watashino_controller.rb      |   1 +
 2 files changed, 1 insertions(+), 14 deletions(-)
```
### -p
-pをつけるとgit diffのように詳細を表示してくれます。

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

## git stash drop
stashで退避させたものを削除します。
末尾にバージョンを記載することで対象を選ぶことも可（記載しない場合は最新のstashを削除する)

```
git stash drop
git stash drop stash@{0}
```

## git stash branch
stashしている物をpopする際に新しくbranchを作成してそこにpopしてくれる
ただしbranchは対象のstashがされたコミットから作成されます。

```
git stash branch hoge  // 現在Stashしている物をhogeというbranchを新規作成したのちにpopする
M   memo/memo20170914.txt
Switched to a new branch 'hoge'
On branch hoge
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   memo/memo20170914.txt
```

これもstashのバージョンを指定することが可能
だいたいgit stash popで競合が発生したときに使用するイメージ

## git stash (save)

変更点を退避させる
saveをつけても同じ動きになる
末尾に"(ダブルクォート)で囲んだ文字列を記載するとメッセージを入れたstashを記載できる。

```
git stash
git stash save
git stash "this is add files"
git stash save "this is add files"
```
### -p|--patch

ファイルの中の変更点のうちどれをstashするかを指定することができる。

```
git stash -p
git stash --patch
```

### -k|--[no-]keep-index

addしていないファイルのみをstashします。

```
git stash -k
git stash --keep-index
git stash --no-keep-index
```

### -q|--quiet
stashのログを表示しない

```
C:\work\hoge>git stash list
stash@{0}: WIP on hoge: 8sje7lk test

C:\work\hoge>git stash -q

C:\work\hoge>git stash list
stash@{0}: WIP on hoge: she9ujh dev
stash@{1}: WIP on hoge: 8sje7lk test
```

### -u|--include-untracked
untrackedなfileも一緒に退避します。

```
git stash -u
git stash --include-untracked
```

### -a|--all
git管理外のファイルも一緒に退避します

```
git stash -a
git stash --all
```

# で、ファイル単位でstashしたいんだけど...

マニュアル見た感じでは方法(option)がなかったので、stashしたいファイル**以外**をaddしたのちにgit stash -k でstash した後にgit reset 使って元に戻しています。

```:実施イメージ
C:\work\hoge>git status
On branch piyo
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   ../memo/hoge.txt
        modified:   ../memo/fuga.txt

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

C:\work\hoge>git add ../memo/hoge.txt

C:\work\hoge>git status
On branch piyo
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   ../memo/hoge.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   ../memo/fuga.txt


C:\work\hoge>git stash -k
Saved working directory and index state WIP on piyo: 19daa6e hoge
HEAD is now at 19daa6e hoge

C:\work\hoge>git status
On branch piyo
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   ../memo/hoge.txt


C:\work\hoge>git reset
Unstaged changes after reset:
M       memo/hoge.txt

C:\work\hoge>git status
On branch piyo
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   ../memo/hoge.txt

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

```