ブランチはなぜ溜まるのか(ahead / behind の読み方と、仕組みで消す話)
GitHub のブランチ一覧の ahead 0 の意味と消してよいブランチの判断、ブランチが溜まる理由と自動削除の設定。
まとめ
- GitHub のブランチ一覧に出る ahead 0 は、main に入っていないコミットが無いという意味で、消しても何も失わない。ただし squash マージや rebase マージの運用では、マージ済みのブランチでも ahead は 0 にならない
- ブランチを残しておくコストを払うのは、作った本人ではなく一覧を見る人だ。だから放っておくと溜まる
- 私自身は、消すことに不安があって残してしまう側だった
- 個人の几帳面さに頼らず、マージした時点で自動で消える仕組みにする
ahead / behind の意味
溜まったブランチを整理しようとして、最初に手が止まったのがブランチ一覧の「ahead 0」だった。 GitHub のブランチ一覧(リポジトリの Branches 画面)には、各ブランチがデフォルトブランチ(ここでは main)とコミット何個ぶんずれているかが出る。
表1: ahead / behind の読み方
| 表示 | 意味 |
|---|---|
| ahead N | そのブランチにだけあって、main に無いコミットが N 個 |
| behind N | main にだけあって、そのブランチに無いコミットが N 個 |
main: A---B---C---D---E
\
feature: Fこの図の feature は ahead 1 / behind 3 になる。 F をコミットしていなければ ahead 0 / behind 3 で、ブランチを切ったまま何もしていない状態だ。
消してよいかの判断
ahead だけで決められるのは、0 のときだけだ。
表2: ahead の値と削除の判断
| 状態 | 削除 | 理由 |
|---|---|---|
| ahead 0 | 消してよい | 中身はすべて main に入っている(通常の merge 済み、または何もコミットしていない) |
| ahead 1 以上で PR が merged | 消してよい | squash / rebase マージではコミットの SHA が変わるため、中身が main に入っていても ahead が残る |
| ahead 1 以上で PR が無い、または closed | 中身を確認してから | main に入っていない作業がある。消すとその作業も消える |
squash マージの運用では、マージ済みのブランチもすべて ahead 1 以上で並ぶ。 ahead だけを見ると、消してよいブランチが軒並み「未マージ」に見えるので、PR の状態と合わせて判断する。 手元の git branch --merged で拾えないのも同じ理由だ(GitHub Squash Mergeのメリットと派生ブランチの落とし穴)。
なぜ溜まるのか
ブランチを整理したくなる理由は、一言でいえば認知負荷だと思う。 作り始めのリポジトリではブランチの数が少なく、整理しようとは思わない。 それが少しずつ積もり、今動いているブランチを一覧から探しにくくなってから、まとめて整理したくなる。
困るのは一覧を見る人で、ブランチを作った本人ではない。 本人は自分のブランチを覚えているので、一覧が長くなっても探す手間はあまり増えない。 消さないコストを払う人と、消す手間を払う人が別々なので、誰かが意識して消さない限り本数は増える一方になる。
私自身は、消すことに不安があって残してしまう側だった。
仕組みで消す
GitHub のリポジトリ設定には、Pull Requests の欄に「Automatically delete head branches」がある。 有効にすると、PR をマージした時点で head ブランチが自動で削除される。 消えたブランチは PR の画面の「Restore branch」で戻せるので、自動で消えても作業は失われない。
この設定なら、マージのたびに誰かが手で消す必要がない。 溜まるかどうかが個人の几帳面さで決まらなくなる。 ただし対象は設定を有効にした後にマージする PR なので、すでに溜まった分は一度手で整理する必要がある(マージ済みのbranchを一括削除)。