Я использовал ответ Адама уже много лет.Тем не менее, есть некоторые случаи, когда он не вел себя так, как я ожидал:
- ветви, которые содержали , слово "master" игнорировалось, например, "notmaster" или "masterful ", а не только основная ветвь
- ветви, которые содержали слово" dev ", игнорировались, например," dev-test ", а не только ветка dev
- удаление ветвей, которые доступны из HEAD текущей ветви (то есть не обязательно главной)
- в отдельном состоянии HEAD, удаление каждой ветви, достижимой изТекущий коммит
1 & 2 был прост для адресации с простым изменением в регулярном выражении.3 зависит от контекста того, что вы хотите (т.е. удаляете только те ветки, которые не были объединены в master или с вашей текущей веткой).4 может привести к катастрофическим последствиям (хотя их можно восстановить с помощью git reflog
), если вы непреднамеренно запустили это в отключенном состоянии HEAD.
Наконец, я хотел, чтобы все это было в одной строке, которая не требовалаотдельный (Bash | Ruby | Python) сценарий.
TL; DR
Создание "развертки" псевдонима git, который принимает необязательный флаг -f
:
git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'
и вызовите его с помощью:
git sweep
или:
git sweep -f
Длинный подробный ответ
Мне было проще всего создать пример git-репо с некоторымиветки и коммиты для проверки правильности поведения:
Создание нового репозитория git с одним коммитом
mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"
Создание нескольких новых веток
git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
bar
develop
foo
* master
masterful
notmaster
Желаемое поведение: выберите все объединенные ветви, кроме: master, development или current
Исходное регулярное выражение пропускает ветви "masterful" и "notmaster":
git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
bar
С обновленным регулярным выражением (которое теперь исключает "развернуть", а не "dev"):
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Переключиться на ветку foo, сделать новый коммит, а затем оформить новую ветку foobar на основе foo:
echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"
My currentветвь - это foobar, и если я перезапущу приведенную выше команду для вывода списка ветвей, которые я хочу удалить, ветка "foo" будет включена, даже если она не была объединена с master:
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
foo
masterful
notmaster
Однако, если я запускаю ту же команду на master, ветка "foo" не включается:
git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
И это простопотому что git branch --merged
по умолчанию - HEAD текущей ветви, если не указано иное.По крайней мере, для моего рабочего процесса я не хочу удалять локальные ветви, если они не были объединены с master, поэтому я предпочитаю следующий вариант:
git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
DetachedСостояние HEAD
Использование поведения по умолчанию git branch --merged
имеет еще более существенные последствия в состоянии отключенного HEAD:
git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
foo
foobar
masterful
notmaster
Это приведет к удалениюВетка у меня была только на «foobar» вместе с «foo», что почти наверняка не желаемый результат.Однако с нашей измененной командой:
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Одна строка, включая фактическое удаление
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d
Все, свернутые в свиток git alias "":
git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'
Псевдоним принимает необязательный флаг -f
.Поведение по умолчанию заключается в удалении только тех веток, которые были объединены в мастер, но флаг -f
удалит ветки, которые были объединены в текущую ветку.
git sweep
Deleted branch bar (was 9a56952).
Deleted branch masterful (was 9a56952).
Deleted branch notmaster (was 9a56952).
git sweep -f
Deleted branch foo (was 2cea1ab).