ブランチ切り替え時に移動先ブランチのstash一覧を表示させる方法


stashしたことを忘れてしまう問題

git stashは非常に便利ですが、他のブランチで作業をしているうちにstashしたことを忘れ、戻ってきた際に再び同じ作業を始めてしまうようなことがたまにあります。

今回はその対策として、
「ブランチを移動するたびに移動先ブランチのstash一覧を表示するGitフック」
を作成したので、その実装方法について解説します。

完成イメージ 

以下のように、移動先ブランチ上でstashしたもののみを表示するイメージです(他のブランチのものは表示しない)。

これなら明らかに通常と違うため stash の存在を思い出せるはずです。

また、元々存在する機能(git hooks)しか使わないため、変なプラグインを入れたりする必要もありません。

実現方法

git の標準機能である git hooks を使います。

git hooksとは.git/hooks/下に置かれたスクリプト群のことで、特定のタイミングで自動的に呼び出される仕組みになっているものです。

例えば「commit 前にリントをしたい」という場合には、pre-commitという名前のファイルを.git/hooks/に配置して、リントを行うコードを書けばOKといった感じです。

今回はgit switchgit checkoutの後に呼ばれてほしいのでpost-checkoutという名前で作成します。

実装

処理の流れを大まかにいうと、
1. git branch --show-currentで移動後のブランチ名を取得し、
2. そのブランチ名をgit stash listの中からgrepする
という感じです。

.git/hooks/post-checkout
#!/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を通して文字色を変更したほうが良いかもしれません。

.git/hooks/post-checkout
#!/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オプションが必要かと思います。より詳しくはこちらの記事をご参照ください。

以上です。改善点等があればコメントやリクエストからご教示いただけると幸いです。