Od lat korzystam z odpowiedzi Adama. To powiedziawszy, że są przypadki, w których nie zachowuje się tak, jak się spodziewałem:
- gałęzie zawierające słowo „master” zostały zignorowane, np. „notmaster” lub „masterful”, a nie tylko gałąź master
- gałęzie zawierające słowo „dev” zostały zignorowane, np. „dev-test”, a nie tylko gałąź dev
- usuwanie gałęzi, które są osiągalne z HEAD bieżącej gałęzi (to znaczy niekoniecznie master)
- w stanie odłączonym HEAD, usuwając każdą gałąź osiągalną z bieżącego zatwierdzenia
Adresy 1 i 2 były łatwe do rozwiązania, z jedynie zmianą wyrażenia regularnego. 3 zależy od kontekstu tego, co chcesz (tj. Usuń tylko te gałęzie, które nie zostały połączone w master lub w stosunku do twojego obecnego oddziału). 4 może być katastrofalne (choć możliwe do odzyskania git reflog
), jeśli przypadkowo uruchomisz to w stanie odłączonej GŁOWICY.
Wreszcie chciałem, aby wszystko było w jednym wierszu, który nie wymagał osobnego skryptu (Bash | Ruby | Python).
TL; DR
Utwórz alias git „Sweep”, który akceptuje opcjonalną -f
flagę:
git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'
i wywołać go za pomocą:
git sweep
lub:
git sweep -f
Długa, szczegółowa odpowiedź
Najłatwiej było mi utworzyć przykładowe repozytorium git z niektórymi gałęziami i zobowiązuje się do przetestowania poprawnego zachowania:
Utwórz nowe repozytorium git za pomocą jednego zatwierdzenia
mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"
Utwórz nowe oddziały
git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
bar
develop
foo
* master
masterful
notmaster
Pożądane zachowanie: wybierz wszystkie połączone gałęzie z wyjątkiem: master, develop lub current
Oryginalne wyrażenie regularne brakuje gałęzi „mistrzowskiej” i „notmistrza”:
git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
bar
Dzięki zaktualizowanemu wyrażeniu regularnemu (które obecnie wyklucza „rozwijanie” zamiast „programowanie”):
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Przejdź do gałęzi foo, dokonaj nowego zatwierdzenia, a następnie sprawdź nowy oddział, foobar, na podstawie foo:
echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"
Moja obecna gałąź to foobar, a jeśli ponownie uruchomię powyższe polecenie, aby wyświetlić listę gałęzi, które chcę usunąć, gałąź „foo” zostanie uwzględniona, nawet jeśli nie została scalona w master:
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
foo
masterful
notmaster
Jeśli jednak uruchomię tę samą komendę master, gałąź „foo” nie zostanie uwzględniona:
git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
A to po prostu dlatego, że git branch --merged
domyślnie HEAD bieżącej gałęzi, jeśli nie określono inaczej. Przynajmniej w moim przepływie pracy nie chcę usuwać lokalnych oddziałów, chyba że zostały scalone w master, więc wolę następujący wariant:
git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Odłączony stan HEAD
Poleganie na domyślnym zachowaniu git branch --merged
ma jeszcze bardziej znaczące konsekwencje w odłączonym stanie HEAD:
git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
foo
foobar
masterful
notmaster
Spowodowałoby to usunięcie gałęzi, na której byłem, „foobar” wraz z „foo”, co prawie na pewno nie jest pożądanym rezultatem. Jednak dzięki naszemu zmienionemu poleceniu:
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster
Jedna linia, w tym faktyczne usunięcie
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d
Wszystko spakowane w alias 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'
Alias akceptuje opcjonalną -f
flagę. Domyślnym działaniem jest usuwanie tylko gałęzi, które zostały scalone w master, ale -f
flaga usunie gałęzie, które zostały scalone w bieżącą gałąź.
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
usuwa każdą gałąź, niezależnie od tego, czy jest scalona czy nie.