Я вже багато років використовую відповідь Адама. Однак, є деякі випадки, коли вона не вела себе так, як я очікувала:
- гілки, які містили слово "майстер", були ігноровані, наприклад, "notmaster" або "masterful", а не тільки головна гілка
- гілки, що містили слово "dev", були ігноровані, наприклад, "dev-test", а не лише гілка dev
- видалення гілок, доступних від HEAD поточної гілки (тобто не обов'язково головного)
- у відірваному стані HEAD, видаляючи кожну гілку, доступну з поточної комісії
1 та 2 були зрозумілі для вирішення, лише змінивши регулярний вираз. 3 залежить від контексту того, що ви хочете (тобто видаляйте лише гілки, які не були об'єднані в головний чи проти вашої поточної гілки). 4 може стати катастрофічним (хоча і підлягає відшкодуванню git reflog
), якщо ви ненавмисно запустили це у відірваному стані HEAD.
Нарешті, я хотів, щоб це все було в одноланковому вкладиші, який не потребував окремого сценарію (Bash | Ruby | Python).
TL; DR
Створіть псевдонім git "sweep", який приймає необов'язковий -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 repo з деякими гілками та зобов’язується перевірити правильність поведінки:
Створіть нове git repo за допомогою одного коміту
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
Бажана поведінка: виберіть усі об'єднані гілки, крім: майстер, розробляти чи поточно
Оригінальний регулярний вираз не вистачає гілок "майстерно" та "немайстра":
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"
Моя поточна гілка є foobar, і якщо я повторно запускаю вищевказану команду для переліку гілок, які я хочу видалити, гілка "foo" включається, навіть якщо вона не була об'єднана в головний:
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 поточної гілки, якщо не вказано інше. Принаймні для мого робочого процесу я не хочу видаляти локальні гілки, якщо вони не були об'єднані в основний, тому я віддаю перевагу наступному варіанту:
git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Стан окремої головки
Опираючись на поведінку за замовчуванням, 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 псевдонім "sweep":
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).
git branch -D
видаляється будь-яка гілка, будь то об'єднана чи ні.