Gitの小ネタおれおれAdvent Calendar 2022 – 15 日目

作業途中の変更をまるっと保存していったん作業ディレクトリーを綺麗にしてくれる git stash 、べんりですよね。

まるっと全部じゃなくて一部だけ保存したい場面があるかもしれません。なんかほら実装しながら勢い余ってリファクタリングも混ざっちゃって別のコミットにしたいけどまだその前にもうちょっと編集したいなみたいなときとか。

-k, --keep-index でステージ追加済みの変更を残す

git add とかした変更は stage されてコミット対象になるんですが(なんて言うのが正確なんだろ、index ?)、git stash push に -k オプションを与えるとそれを残して stash の保管庫へ送ってくれます。

例

例えば README.md を変更して、これを git add で stage へ追加します。

-# Original
+# Updated
$ git add README.md

その後また編集した状態です。

-# Updated
+# Updated again
$ git status
…

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   README.md

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:   README.md

この状態で普通に git stash すると README.md の内容は最初の “Original” に戻ってしまいます。

そこで -k です。git stash -k なら stage されている変更は残すので、README.md の内容は戻っても “Updated” までです。

$ git stash -k
Saved working directory and index state WIP on main: 7f3301d361f Woo foo
$ git status 
On branch main
Your branch is behind 'origin/main' by 102729 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   README.md

-p, --patch で変更を選択しながら残す

git add にもある -p が git stash にもあります。ただし -u や -a は使えないので、新規作成したファイル対象には利用できません。-k でまるごとなら。

$ git stash -k -p
diff --git a/README.md b/README.md
index 672de4d..b8c64c1 100644
--- a/README.md
+++ b/README.md
@@ -1,1 +1,1
-# Updated
+# Updated again
(1/1) Stash this hunk [y,n,q,a,d,s,e,?]?

おしまい

あんまりこねこねしてもなんか衝突起こしてすぐ git stash pop できなくなっちゃう印象。

あと git stash -p は使ったことないや。

参考