stash

Stash the changes in a dirty working directory away
変更を一時的な作業ディレクトリに隠しておく
Git - git-stash Documentation

「とあるブランチで作業中だけど、いますぐやりたいことができた。作業がすごく中途半端だからコミットはしたくない。」
【git stash】コミットはせずに変更を退避したいとき - Qiita

変更を退避する

git stash -u

  • コミットしていない変更がある状態でコマンド実行で、変更した部分が退避される
    • ワーキングディレクトリ上は差分がない状態になる
    • 「コミットしていない変更」とは、addしたものもaddしていないものもどちらも含まれる
  • -u は --include-untracked
    • 新規作成ファイルも退避できる

退避した作業の一覧 (list)

git stash list

stash@{0}: WIP on test: xxxx
stash@{1}: WIP on commit-sample: xxxx
  • stash@{n}から始まる1行が1回分のstash
  • WIP on <ブランチ名>
    • xxxxはstashをしたときのHEADのコミットハッシュとコミットメッセージ

退避した作業を戻す (apply)

git stash apply stash@{0}
stash@{0} の作業をもとに戻す場合)

  • 現在チェックアウトしているブランチへ、退避した変更が戻る
    • 変更を退避したときのブランチにも、それ以外のブランチにも戻すことができる
  • stash名は省略可
    • 省略した場合は、直近にstashした情報が戻る
  • オプション無しの場合、addしていた変更もaddされていない状態で戻る (stagedされていた変更もnot stagedととして戻る)
    • addした状態そのままにもどしたいときは、--index オプションを付けて実行

git stash apply stash@{0} --index

退避した作業を消す (drop)

git stash drop stash@{0}

  • stash@{0} をstashのリストから削除
  • stashを使用して退避した作業を元に戻しても、退避した情報は残ったまま
  • apply と同様に、 stash名(stash@{0})を省略すると、直近にstashした情報を削除する

退避した作業を元に戻す & stashのリストから消す (pop = apply + drop)

git stash pop stash@{0}

  • stash@{0} の作業をもとに戻す & 退避作業の中から削除
  • こちらもstash名(stash@{0})省略で、直近にstashした情報を消すことができる
  • 退避した変更をもとに戻す際、コンフリクトが発生する場合もある(?)
    • これは apply + drop 時も同じでは?

作業を退避するときにメッセージを付ける

git stash save "stash message"

git stash list
stash@{0}: On test: stash message

退避した変更の詳細をみる

git stash show stash@{0}

  • 変更ファイルの一覧を見ることができる
  • また、-p オプションをつけることで、変更内容の詳細をみることもできる

git stash show stash@{0} -p

addした変更以外を退避させる

  • オプションなしの場合、addした変更もaddしていない変更も退避される(新規追加ファイルは退避しない → する場合は -u)
  • -k (--keep-index)をつけて実行すると、addした変更は退避されない

git stash -k

退避した作業をすべて消す

git stash clear

実際にやってみる

  • メインブランチ、トピックブランチそれぞれでコミットがある状態を作っておく
  • トピックブランチで作業 → メインブランチをチェックアウト
    • エラーになる
% gl
* 7d0e1a8 (HEAD -> dev) dev 1
* 35a1131 (main) main 1
* 088c790 first commit
% vi dev.txt 

% gck main 
error: Your local changes to the following files would be overwritten by checkout:
    dev.txt
Please commit your changes or stash them before you switch branches.
Aborting
  • コミットしないままメインブランチにチェックアウトしたいので、stash を使う
% g stash -u
Saved working directory and index state WIP on dev: 7d0e1a8 dev 1
  • stash 一覧を確認
% g stash list 
stash@{0}: WIP on dev: 7d0e1a8 dev 1
  • 一度メインブランチにチェックアウト、またトピックブランチに戻る
    • 今度はチェックアウト時にエラーが出ない
% gck main 
Switched to branch 'main'

% gck dev  
Switched to branch 'dev'
  • 退避した作業を戻す
    • git stash apply stash@{n}stash@{n} を省略すると、直近の stash が復元される
% g stash apply 
On branch dev
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:   dev.txt

no changes added to commit (use "git add" and/or "git commit -a")
  • stash 一覧を確認
    • apply しても stash は残ったまま
% g stash list 
stash@{0}: WIP on dev: 7d0e1a8 dev 1
  • 退避した作業を消去する
    • こちらも apply 同様にスタッシュ名省略で、直近のスタッシュにコマンドが適用される
    • 不要な stash が山積みな状態はよろしくないとのこと
  • 削除して再びリスト一覧を確認
% git stash drop 
Dropped refs/stash@{0} (e062fadbd538c5cdd800338bab759e1c00d8822d)

% g stash list 
# stash は無い
  • stash pop を使って applydrop を一度にまとめて実行する
  • まず、メインブランチにチェックアウトしようとするとエラーになることを確認し、stash で退避させ、メインブランチにチェックアウト → トピックブランチに戻る
% gck main
error: Your local changes to the following files would be overwritten by checkout:
    dev.txt
Please commit your changes or stash them before you switch branches.
Aborting

% g stash -u
Saved working directory and index state WIP on dev: 7d0e1a8 dev 1

% gck main 
Switched to branch 'main'

% gck dev 
Switched to branch 'dev'
  • stash pop を実行
    • こちらも apply 同様にスタッシュ名省略で、直近のスタッシュにコマンドが適用される
  • stash 一覧を確認
    • stash は pop によって削除されたため何も無い状態
% g stash pop
On branch dev
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:   dev.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (bf0c1a576122350a8ddc12176338664b7f1f0cea)
~/Downloads/s (dev *)
% g stash list
# stash は無い
  • 退避するときにメッセージを付ける
    • リスト一覧でメッセージを確認できる
% g stash save "hogehoge"
Saved working directory and index state On dev: hogehoge
~/Downloads/s (dev $)
% g stash list 
stash@{0}: On dev: hogehoge
  • 退避した作業をすべて消す
% g stash list 
stash@{0}: On dev: hogehoge
~/Downloads/s (dev $)
% g stash clear 
~/Downloads/s (dev)
% g stash list 
# stash は無い