動機
Git で、編集途中のファイルを git stash して、別のブランチに移動することがあります。作業が終わって元のブランチに戻ってきた時に、stash pop するのを忘れたり見失ったりしそうで不安でした。
今のブランチで実行した stash の一覧を表示して pop する方法があるのでは、と思ったのですが、それらしいのが見つからなかったので作りました。
特に最近は、毎朝、TODO リストにある全タスクに 10 分ずつ着手する、という作業のスタイルを試していて、たくさんの stash を管理するのに役に立っています。
スクリプト
以下を git-bpop というファイル名でパスの通った場所に保存します。
# ! /bin/bash
set -e
BRANCH=$(git rev-parse --abbrev-ref HEAD)
STASH=$(git stash list | grep -F ": WIP on $BRANCH:" | tail -r)
IFS=$'\n'
for S in $STASH; do
REV=$(echo "$S" | sed -e 's/^\(stash@{[0-9]*}\):.*/\1/')
echo '------------------------------------'
echo $S
echo '------------------------------------'
if [ "$1" = 'pop' -o "$1" = 'p' ]; then
git --no-pager diff "HEAD...$REV"
echo
git stash pop "$REV"
exit
else
git diff "HEAD...$REV"
fi
done
やっていることは、git stash list で表示される WIP on ブランチ名 を、今のブランチ名で grep して、diff、stash pop しているだけです。複数の stash が見つかったら一番古いものを pop します。
使い方
作業中のブランチから離れるときに、普通に git stash します。
## 現在のブランチは branch-1
$ git branch
* branch-1
master
## 何か変更します。
$ echo bbb >> test.txt
## 別の作業が発生したので、変更を stash して、
$ git stash
Saved working directory and index state WIP on branch-1: 90dd8a9 init
HEAD is now at 90dd8a9 init
## master に移動します。
$ git checkout master
Switched to branch 'master'
## master ブランチには stash が無いことを確認。
$ git bpop
$
別の作業が終わって、最初のブランチに戻ってきたら、$ git bpop で stash の diff を確認します。
$ git checkout branch-1
Switched to branch 'branch-1'
$ git bpop
------------------------------------
stash@{0}: WIP on branch-1: 90dd8a9 init
------------------------------------
diff --git a/test.txt b/test.txt
index 72943a1..dbee026 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
aaa
+bbb
diff を適用して問題なさそうだったら、$ git bpop pop で stash pop します。
$ git bpop pop
------------------------------------
stash@{0}: WIP on branch-1: 90dd8a9 init
------------------------------------
diff --git a/test.txt b/test.txt
index 72943a1..dbee026 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
aaa
+bbb
On branch branch-1
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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped stash@{0} (076c635f56852e3c367f0fd435d906852894a7c3)
他のアイディア
当初は git checkout 時に自動で stash pop することを考えていました。全ての stash が全部自動で適用されてしまうのはナシかなと思って止めましたが、、。
「次回必ず pop する」マーク付きで stash するコマンドを作って、pop はフックで実行する、みたいなのも便利かもしれません。