stashしたことを忘れてしまう問題
git stash
は非常に便利ですが、他のブランチで作業をしているうちにstashしたことを忘れ、戻ってきた際に再び同じ作業を始めてしまうようなことがたまにあります。
今回はその対策として、
「ブランチを移動するたびに移動先ブランチのstash一覧を表示するGitフック」
を作成したので、その実装方法について解説します。
完成イメージ
以下のように、移動先ブランチ上でstashしたもののみを表示するイメージです(他のブランチのものは表示しない)。
これなら明らかに通常と違うため stash の存在を思い出せるはずです。
また、元々存在する機能(git hooks)しか使わないため、変なプラグインを入れたりする必要もありません。
実現方法
git の標準機能である git hooks を使います。
git hooksとは.git/hooks/
下に置かれたスクリプト群のことで、特定のタイミングで自動的に呼び出される仕組みになっているものです。
例えば「commit 前にリントをしたい」という場合には、pre-commit
という名前のファイルを.git/hooks/
に配置して、リントを行うコードを書けばOKといった感じです。
今回はgit switch
やgit checkout
の後に呼ばれてほしいのでpost-checkout
という名前で作成します。
実装
処理の流れを大まかにいうと、
-
git branch --show-current
で移動後のブランチ名を取得し、 - そのブランチ名を
git stash list
の中からgrep
する
という感じです。
#!/bin/sh
has_branch_changed=$3 #ブランチ移動したかどうかのフラグ
current_branch=$(git branch --show-current | awk -F/ '{print $NF}')
if [ $has_branch_changed = 1 ] && [ -n "$current_branch" ]; then
git stash list | grep "$current_branch: "
fi
結果
※ 説明のため、ここではまだ文字色の変更等は行っていません。色付きバージョンのコードは次節をご参照ください。
技術的な詳細
-
git checkout
してもブランチが変わっていないケースもあるため、post-checkout
の三番目の引数$3
(ブランチ移動したかどうかのフラグ)を使ってチェックを入れています。ちなみに$1
には移動元のcommit hash,$2
には移動先のcommit hashが入っています。 -
awk -F/ '{print $NF}'
はブランチ名を/
で分割して末尾部分を取得するコードです。この処理が必要なのは、ブランチ名が/
で区切られている場合git stash list
は区切りの末尾の部分しか表示しないためです。例えばaaa/bbb/ccc
ならccc
の部分しか表示しないため、単純にgrep <ブランチ名>
では取得できません。 -
[ -n "$current_branch" ]
でブランチ名が1文字以上かのチェックを行っていますが、これは detached HEAD の場合ブランチ名が出力されず、結果的に全ての stash が表示されてしまうためです。
もっと目立たせる
上記のコードでは文字色の変更等は行っていませんでした。
しかしより視認性を高めるためにはecho
を通して文字色を変更したほうが良いかもしれません。
#!/bin/sh
has_branch_changed=$3 #ブランチ移動したかどうかのフラグ
current_branch=$(git branch --show-current | awk -F/ '{print $NF}')
if [ $has_branch_changed = 1 ] && [ -n "$current_branch" ]; then
git stash list | grep "$current_branch: " | while read line; do
echo "🐿 \033[32m$line\033[m"
done
fi
結果
前節のコードの出力をwhile read
で回して、echo
で色と絵文字を付加しているだけです。
※ **echo
の文字色の変更法はシェルによって異なります。**例えば bash の場合は-e
オプションが必要かと思います。より詳しくはこちらの記事をご参照ください。
以上です。改善点等があればコメントやリクエストからご教示いただけると幸いです。