にわとりプログラマーの備忘録

覚えたことをすぐ忘れてしまう、自分のための備忘録ブログです。

履歴からブランチをチェックアウトする Gitエイリアス

業務中に1日に3,4個のブランチを行ったり来たりする時が往々にしてあり、タスクごとにブランチ名を記憶して切り替えるのは、記憶力の悪い自分にとっては非常にストレスフルな作業でした。

そこで、ブランチ移動履歴からブランチを選択してブランチ切り替えできる Gitエイリアスを設定してみたら、かなり快適に作業ができるようになりました!

[alias]
history = "!f() { git --no-pager reflog | awk '$3 == \"checkout:\" && /moving from/ {print $8}' | awk 'a[$0]++ == 0' | head | peco | xargs git checkout; }; f"

f:id:t-yng:20190427234504g:plain

エイリアスの詳細

操作履歴の一覧を取得

$ git --no-pager reflog
1de01c5 (HEAD -> master) HEAD@{0}: checkout: moving from test-3 to master
71d27e1 (test-3) HEAD@{1}: commit: commit in test-3
1de01c5 (HEAD -> master) HEAD@{2}: checkout: moving from master to test-3
1de01c5 (HEAD -> master) HEAD@{3}: checkout: moving from test-2 to master
45b93f3 (test-2) HEAD@{4}: commit: commit in test-2
1de01c5 (HEAD -> master) HEAD@{5}: checkout: moving from master to test-2
1de01c5 (HEAD -> master) HEAD@{6}: checkout: moving from test-2 to master
4ddaa52 (test-1) HEAD@{7}: checkout: moving from test-1 to test-2
4ddaa52 (test-1) HEAD@{8}: commit: test-1 commit
1de01c5 (HEAD -> master) HEAD@{9}: checkout: moving from master to test-1
1de01c5 (HEAD -> master) HEAD@{10}: checkout: moving from test-1 to master
1de01c5 (HEAD -> master) HEAD@{11}: checkout: moving from master to test-1
1de01c5 (HEAD -> master) HEAD@{12}: commit (initial): first commit

reflog はデフォルトでページャされるので、 --no-pager を指定して ページャせずに出力をパイプで渡すようにしています。

移動履歴のブランチを抽出

$ git --no-pager reflog | awk '$3 == "checkout:" && /moving from/ {print $8}'
master
test-3
master
test-2
master
test-2
test-1
master
test-1

$3 == "checkout:" でチェックアウト操作のみに絞り込み、 /moving from/ にてブランチ移動だけを対象として、{print $8} で移動先のブランチを出力しています。

ブランチ名の重複を削除

$ git --no-pager reflog | awk '$3 == "checkout:" && /moving from/ {print $8}' | awk 'a[$0]++==0'
master
test-3
test-2
test-1

uniqを利用した場合は sort & uniq を実行する必要があり、処理が多くなってしまうので、awkで重複を排除しています。

ブランチを選択して切り替え

最後に peco に出力を渡して、選択されたブランチにチェックアウトすれば完了です。

$ git --no-pager reflog | awk '$3 == "checkout:" && /moving from/ {print $8}' | awk 'a[$0]++==0' | head | peco | xargs git checkout
master
test-3
test-2
test-1

対象ブランチを移動履歴の最新10件のみに絞り込むために、headを途中で挟んでいます。
対象のブランチを上限したい時は head -n {行数} で調整が可能です。

さいごに

想像していた以上に便利に使えていて満足です。
余談ですが、シェルスクリプトワンライナーはパーツが組み合わさりデータが少しずつ整理されていく過程に美しさを感じて非常に気持ち良いです!