• 作成:
  • 更新:

git pullした時に削除済みのリモートブランチとマージ済みのローカルブランチを自動削除する

GitHub Flowのように細かく機能別にブランチを分けてpull requestを作っていく形式だとブランチのゴミが鬱陶しくて仕方が無くなります.

Gitにはgit fetch --pruneというオプションがあり, これでリモートブランチは削除を検知して消してくれます. しかしローカルブランチはそのままです.

なんでそのままなのかわからないのですが, とりあえず削除するのがいい加減面倒になってきたので, シェルスクリプトを書くことにしました.

これ自体はGit でマージ済みのブランチを一括削除する - Qiitaを参照にして簡単に出来ました.

parallel --no-notice git branch -d {} ::: $(git branch --merged|ag -v '\*|master')

git branch -d {} master, git branch --merged masterとするとmasterを基準にして, masterに一々チェックアウトしないで済むようになります. しかし代わりにmasterブランチ以外にマージ済みのゴミブランチが消せなくなるので, 引数を与えずに現在のブランチに依存する形式にしました. 再初に書いた当時は全部baseがmasterだったので問題なかったのですが, 別ブランチから切り出し作業をするのが多くなったので考え直しました.

しかしシェルスクリプトを一々実行するのは面倒くさいですね. 私は普段Git操作はIt's Magit! A Git Porcelain inside Emacsを使っていて, 一々コンソールに戻ってGit操作したくはないので尚更です.

hookを使って自動実行するようにしましょう.

~/Documents/hooks/post-merge

#!/usr/bin/env zsh
parallel --no-notice git branch -d {} ::: $(git branch --merged|ag -v '\*|master')

と記述します.

git config --global core.hooksPath ~/Documents/hooksと設定します.

さらにgit config --global pull.prune trueと設定します.

これでgit pullしてmergeが走ったとき, 自動でリモートブランチの削除を検知して, ローカルブランチも削除してくれます.

これまで

  • git fetch -pして削除されたリモートブランチを削除
  • git pullしてmasterにコミットをmerge
  • git branch -dでmergeされたブランチを削除

を手動で行っていたのがgit pullを行えば良いだけになってくれました.

しかし, 肝心のMagitを使ったgit pullでpruneが動きません. Magitはgit configの設定を見ないようですね. Magitで使ってもhookが動いてローカルブランチを削除してくれるようになっただけマシなのですが… どなたかMagitでgit pull時にpruneする設定をご存知ないでしょうか. Magitにpull requestを送るしかない?

hookにgit fetch --pruneを書くことで解決しました.

#!/usr/bin/env zsh
parallel --no-notice git branch -d {} ::: $(git branch --merged|ag -v '\*|master')
git fetch --prune

これでgit pullするだけで良くなりました.

現在の全体スクリプト追記

現在(2022-02-03)は、 dotfiles/delete-merged-branch at master · ncaq/dotfiles に以下のようなスクリプトを置いて、 post-mergeで実行しています。

#!/bin/bash
set -eu
default_branch=$(git symbolic-ref refs/remotes/origin/HEAD|sed 's@^refs/remotes/origin/@@')
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [[ $default_branch != $current_branch ]]; then
  exit 0
fi
git branch --merged|grep --invert-match -E "\\*|${default_branch}"|xargs --no-run-if-empty git branch --delete
git fetch --prune

主にGitHubなどがデフォルトブランチがmasterではなくmainにしたりするのでそれに対応して、基本的なUNIXコマンドだけを使うことで移植性を高めています。