Git

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は退避できない(オプション次第ではできる)
基本的には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 st
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")