LoginSignup
24
10

More than 1 year has passed since last update.

[Python] ローカルのgitのブランチをお掃除するスクリプトを書いた

Posted at

はじめに

みなさんローカルに溜まっていくgitのブランチをどのように整理していますか?

自分は

$ git branch
foo
bar
baz

$ git branch -D bar baz
$ git branch
foo

のように、 git branch で一覧を表示した後、不要なものをコピペして削除していました。

prune--merged を使えば、マージされているブランチを
いい感じに 削除できるようですが、
「一覧から好きなものを選んで削除したい!」と思ったので、作ってみました。

簡単にコマンドライン上でのチェックボックスを実装できるライブラリはないかなと探し、
PyInquirer を見つけたので、これを使いました。

完成したもの(gif)

sweep_branch.gif

実装

やりたいことの整理

やりたいことは、
1. ブランチ一覧の取得
2. 一覧からの複数選択
3. 選択したブランチの一括削除
です。

1, 3については はじめに でも書いたように

$ git branch
$ git branch -D foo bar baz

で実現できるます。
これらはPythonスクリプト内で subprocess を使って実行するようにして、

最終的なスクリプトは以下のようになるイメージで進めます。

if __name__ == '__main__':
    output = subprocess.check_output(['git', '-P', 'branch'])

    # output から branch_list を抽出する処理
    # ...

    subprocess.call(['git', 'branch', '-D'] + delete_branch_list)

2について PyInquirer を使って実装し、
選択したブランチの一覧を git branch -D に渡すような処理を書いていきます。

PyInquirerの挙動確認


実装する前にまず、PyInquirer の使い方について簡単に触れます。
quickstartには

you define a list of questions and hand them to prompt
prompt returns a list of answers

と書かれています。

今回は複数選択のためにチェックボックスを使いたいので、
Pyinquireが用意してくれているexample
を少し見ます。

exampleを少し編集して、挙動を確認します。

from pprint import pprint

from PyInquirer import prompt, Separator

questions = [
    {
        'type': 'checkbox',
        'qmark': '😃',
        'message': 'Select toppings',
        'name': 'toppings',
        'choices': [
            {'name': 'Ham'},
            {'name': 'Ground Meat'},
            {'name': 'Bacon'}
        ]
    },
    {
        'type': 'checkbox',
        'qmark': '🧀',
        'message': 'Select toppings2',
        'name': 'toppings2',
        'choices': [
            {'name': 'Mozzarella',},
            {'name': 'Cheddar'},
            {'name': 'Parmesan'},
        ]
    }
]
answers = prompt(questions)
pprint(answers)

実行すると
まずquestionsの一つ目のchoicesが表示されました。
image.png

次に二つ目のchoicesが表示。
image.png

最後にそれぞれで選択したchoicesの結果
image.png

が得られました。

quickstartに書いてある通りですが
prompt は、引数に渡した questions を順番に実行し、
各questionの回答を辞書に詰めて返してくれることが分かりました。

(チェックボックスは List で返してくれる)

では PyInquirer の挙動が確認できたので実装します。

お掃除スクリプト実装

上で試した結果、promptに渡す questionsをこのようにすれば良さそうです。

branch_choices = [
    {'name': 'foo'},
    {'name': 'bar'},
    {'name': 'baz'}
]
questions = [
    {
        'type': 'checkbox',
        'name': 'delete_branch_list',
        'message': '削除するブランチを選択',
        'choices': branch_choices
    }
]

なので、まず branch_choices を作成する処理を書きます。

# -P オプションをつけることで paginate なしでブランチの一覧を取得できる
output = subprocess.check_output(['git', '-P', 'branch'])
# split('\n')で最後に改行分の空文字が入ってくるので[:-1]とする
branch_choices = [
    {'name': branch_name.replace(' ', '').replace('*', '')}
    for branch_name in output.decode().split('\n')[:-1]
]

ではこれをchoicesとするquestionsをpromptに渡します。

questions = [
    {
        'type': 'checkbox',
        'name': 'delete_branch_list',
        'message': '削除するブランチを選択',
        'choices': branch_choices
    }
]

answers = prompt(questions)

これでanswersに delete_branch_list という key で、
選択したブランチのlistを詰めて返してくれるようになりました。

一応、選択なしだった時のif文等を追加して、完成させます。

↓が完成物です。

# -*- coding: utf-8 -*-

import sys
from PyInquirer import prompt, Separator
import subprocess



output = subprocess.check_output(['git', '-P', 'branch'])
# split('\n') で最後に空文字が入ってくるので[:-1]としている
branch_choices = [
    {'name': branch_name.replace(' ', '').replace('*', '')}
    for branch_name in output.decode().split('\n')[:-1]
]
questions = [
    {
        'type': 'checkbox',
        'name': 'delete_branch_list',
        'message': '削除するブランチを選択',
        'choices': branch_choices
    }
]

answers = prompt(questions)

if not answers:
    sys.exit()

delete_branch_list = answers.get('delete_branch_list')

if not delete_branch_list:
    print('選択されたブランチはありませんでした。')
    sys.exit()

subprocess.call(['git', 'branch', '-D'] + delete_branch_list)

おわり

PyInquirer 非常に便利でした。

ありがとうございました。

24
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
10