Jak mogę usunąć wszystkie gałęzie Git, które zostały scalone?


1933

Mam wiele oddziałów Git. Jak usunąć oddziały, które już zostały scalone? Czy istnieje prosty sposób na usunięcie ich wszystkich zamiast usuwania ich pojedynczo?


46
Aby być bardziej szczegółowym, git branch -Dusuwa każdą gałąź, niezależnie od tego, czy jest scalona czy nie.
PhilT

12
Możesz to również zrobić bezpośrednio z GitHub, jeśli przejdziesz do sekcji „oddziały” swojego repozytorium (np. Github.com/<nazwa_użytkownika>/<nazwa_pojęć>/gałęzi ). Powinna być lista wszystkich twoich gałęzi, z czerwoną ikoną kosza na śmieci z boku, która usunie wybraną gałąź. Znacznie szybciej niż w terminalu! Pokaże także, jak daleko do przodu / do tyłu jest masterkażda gałąź. Jednak twój lokalny klient nadal będzie wyświetlał listę starych oddziałów, jeśli uruchomisz git branch -a; użyj, git fetch --pruneaby je usunąć (zgodnie z tą odpowiedzią ).
user5359531

3
Skrypt, aby to zrobić lokalnie lub zdalnie - z kontrolami bezpieczeństwa i wstępnie skonfigurowanymi „bezpiecznymi oddziałami”: github.com/fatso83/dotfiles/tree/master/utils/… git delete-merged --doit origin lubgit delete-merged --doit --local
oligofren

Możesz także użyć tej aplikacji do automatycznego usuwania scalonych oddziałów.
Sebass van Boxel,

rm -fr work && git clone http://example.com/work.gitz biegiem lat stał się najłatwiejszym sposobem na wyjście z marynaty za pomocą git.
Reactgular

Odpowiedzi:


3114

AKTUALIZACJA:

Możesz dodać inne gałęzie, aby wykluczyć takie jak master i dev, jeśli Twój przepływ pracy ma je jako możliwy przodek. Zwykle rozgałęziam się od znacznika „sprint-start” i master, dev i qa nie są przodkami.

Najpierw wypisz wszystkie gałęzie, które zostały scalone zdalnie.

git branch --merged

Możesz zobaczyć kilka gałęzi, których nie chcesz usunąć. możemy dodać kilka argumentów, aby pominąć ważne gałęzie, których nie chcemy usuwać, jak master lub develop. Następujące polecenie pominie gałąź master i wszystko, co ma w niej dev.

git branch --merged| egrep -v "(^\*|master|dev)"

Jeśli chcesz pominąć, możesz dodać go do polecenia egrep w następujący sposób. Oddział skip_branch_namenie zostanie usunięty.

git branch --merged| egrep -v "(^\*|master|dev|skip_branch_name)"

Aby usunąć wszystkie lokalne oddziały, które są już połączone w aktualnie wyewidencjonowany oddział:

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

Możesz zobaczyć, że mistrz i dev są wykluczeni, jeśli są przodkami.


Możesz usunąć scalony oddział lokalny za pomocą:

git branch -d branchname

Jeśli nie jest scalony, użyj:

git branch -D branchname

Aby usunąć go ze zdalnego użycia:

git push --delete origin branchname

git push origin :branchname    # for really old git

Po usunięciu gałęzi ze zdalnego możesz przycinać, aby pozbyć się gałęzi zdalnego śledzenia za pomocą:

git remote prune origin

lub przycinaj poszczególne gałęzie zdalnego śledzenia, jak sugeruje druga odpowiedź, za pomocą:

git branch -dr branchname

Mam nadzieję że to pomoże.


46
OSTRZEŻENIE: Jeśli właśnie utworzyłeś gałąź, ta również ją usunie. Upewnij się, że na liście nie ma nowo utworzonego oddziału, zanim uruchomisz najwyższą komendę.
Gary Haran

153
PRZECIWKO OSTRZEŻENIE: reflog uratuje twój bekon. Więc nie martw się.
Adam Dymitruk,

33
Pamiętaj, że pierwsze polecenie usuwa tylko lokalne oddziały, więc nie jest tak „niebezpieczne”, jak niektórzy wskazywali.
ifightcrime

79
Wariant programu PowerShell, aby móc go tu znaleźć następnym razem, gdy git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
przejrzałem

23
Powoduje to błąd, fatal: branch name requiredjeśli nie masz gałęzi, które należy usunąć. Aby tego uniknąć, możesz przekazać, -raby xargsnie działał, git branch -djeśli standardowe wejście jest puste. (To rozszerzenie GNU xargs, zgodnie ze stroną man).
Marius Gedminas,

455

Aby usunąć wszystkie gałęzie na pilocie, które są już scalone:

git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin

W nowszych wersjach Git

git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin

AKTUALIZACJA (autor @oliver; ponieważ nie mieści się w komentarzu, ale wystarczająca liczba odpowiedzi) : jeśli jesteś na gałęzi ABC, to ABC pojawi się w wynikach, git branch -r --mergedponieważ gałąź nie jest określona, ​​więc gałąź domyślnie przyjmuje gałąź bieżącą i gałąź zawsze kwalifikuje się jako scalony z samym sobą (ponieważ nie ma różnic między gałęzią a sobą!).

Więc albo określ gałąź:

git branch -r --merged master | grep -v master ...

LUB pierwszy główny kasjer:

git checkout master | git branch -r --merged | grep -v ...

18
Jak dotąd najlepsza odpowiedź. Tylko uwaga, moja główna gałąź ma nazwę, devwięc musiałem to zmienić
Dorian

41
Musiałem dodać | grep originpo, grep -v masteraby zapobiec wypychaniu gałęzi innych pilotów do źródła. git branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
Zdecydowanie

9
Lekko zmodyfikowałem, aby wykluczyć również developgałąź. git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin. Teraz okazało się, że to mój pseudonim.
sarat

8
To, co uczyniło tę najlepszą odpowiedź, jaką przeczytałem, to -rargument, o którym nigdzie indziej nie wspominałem. Jest rzeczą oczywistą, że tylko lokalne oddziały są warte sprzątania. Ale piloty też są pełne śmieci.
Asbjørn Ulsberg,

19
Uwaga - właśnie zdałem sobie sprawę: to oczywiście spowoduje, że gałęzie scalone z bieżącą gałęzią , a nie master, więc jeśli jesteś na myFeatureBranchniej, to wyczyścisz origin/myFeatureBranch. Prawdopodobnie najlepiej git checkout masternajpierw.
jakub.g

190

Po prostu rozszerzając nieco odpowiedź Adama:

Dodaj to do konfiguracji Gita, uruchamiając git config -e --global

[alias]
    cleanup = "!git branch --merged | grep  -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d"

A następnie możesz usunąć wszystkie lokalne połączone gałęzie w prosty sposób git cleanup.


11
nie powinno być pierwszym poleceniem: git branch --merged masterskoro chcesz spojrzeć na to, co zostało scalone w master, aktualnie nie sprawdzoną gałąź?
Joe Phillips,

@JoePhilllips Niektórzy ludzie ma główny oddział nie główny ale zamiast developlub devw takim przypadku komenda nie powiedzie się fatal: malformed object name, że lepiej jest mieć ogólne polecenia i masz obowiązek go uruchomić
smohamed

1
@JoePhilllips Celem tej odpowiedzi jest spakowanie odpowiedzi Adama (najważniejszej odpowiedzi na to pytanie) w pomocny alias git. Odpowiedź Adama nie zawiera tego, co sugerujesz, i tak wiele osób uznało to za przydatne, więc byłbym skłonny nie zmieniać mojej.
Poleciłbym

13
Dodanie -rdo xargszapobiegnie niepotrzebnym błędom ( branch name required) podczas wielokrotnego uruchamiania tego aliasu lub gdy nie ma już gałęzi do usunięcia. Mój pseudonim wygląda następująco:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta

1
Obecne polecenie nie odfiltrowuje master i nie rozwija gałęzi
Andriy F.

83

Działa to również w celu usunięcia wszystkich scalonych gałęzi oprócz master.

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d

3
Teraz nie usunie żadnej gałęzi master. Spróbuj grep -v ^master$na środku.
wchargin

Pozwoliłbym również | grep -v '^\*'uniknąć usuwania bieżącej gałęzi, jeśli nie jesteś na master
svassr

5
To wspaniale, dzięki! Jedno zastrzeżenie dla każdego, kto tego używa: pamiętaj, że są w nim dwie spacje grep -v '^ master$'. Jeśli wpiszesz go w sobie i przegapisz, usuniesz go, masterjeśli go nie ma.
styger

3
@ Mr.Polywhirl Twoja edycja łamie polecenie i powinieneś je cofnąć. Dwie spacje są konieczne, ponieważ git branchwyświetli nazwę każdej gałęzi w nowym wierszu z dwiema spacjami po lewej, jeśli nie jest to gałąź aktualnie wypisana. Zasadniczo masz gwarancję, że każdy, kto uruchomi to polecenie, usunie swoją gałąź główną, chyba że jest to gałąź aktualnie wypisana.
styger

79

Będziesz chciał wykluczyć gałęzie masteri developz tych poleceń.

Lokalny git wyczyść:

git branch --merged | grep -v '\*\|master\|develop' | xargs -n 1 git branch -d

Zdalne git wyczyść:

git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin

Synchronizuj lokalny rejestr zdalnych oddziałów:

git fetch -p

3
+1 również dla wersji zdalnej (ale mniej potrzebne, ponieważ mamy zdalną - przycinanie). Warto również zauważyć, że ta opcja nie będzie działać ze starszą wersją git
malko

4
git config --global --add fetch.prune trueprzycinać automatycznie przy pobieraniu lub ciągnięciu.
T3rm1,

1
Pamiętaj, że suszona śliwka to nie to samo, co zdalne oczyszczanie. Zdalne czyszczenie faktycznie usuwa zdalne gałęzie, które są całkowicie scalone z bieżącą gałęzią. Przycinanie czyści tylko lokalny rejestr zdalnych oddziałów, które zostały już usunięte.
Guido Bouman

Słowo w pełni jest nieco mylące, ponieważ gałąź zostanie uznana za scaloną, gdy była wcześniej scalona, ​​ale po scaleniu ma nowe zatwierdzenia, które nie zostały scalone.
budzi

Aby usunąć wszystkie piloty git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
źródłowe

48

Dla tych z was, którzy są w systemie Windows i wolą skrypty PowerShell, oto jeden, który usuwa lokalne połączone gałęzie:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}

13
Ze względu na ciekawość można to skrócić do git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Iain Ballard

5
@IllBallard Jasne, mogłem użyć aliasów. Nie jest to zalecane, jeśli chcesz zmaksymalizować czytelność. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Klas Mellbourn

1
pewnie. Uważam, że twoja odpowiedź jest bardzo pomocna :-) Jednak czasem długa forma składni PowerShell przeszkadza w tym, co dzieje się w blokach. Ale przede wszystkim zaproponowałem coś, co możesz skopiować / wkleić lub wpisać jako jednorazowe. Dzięki jeszcze raz.
Iain Ballard

4
Oto jednowierszowa powłoka cmd Windows, która zachowuje master i twoją obecną gałąź: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(westchnij, zamień podwójne cudzysłowy na pojedynczy, nie jestem pewien, jak sformatować literał zawierający cudzysłowy)
yoyo

42

Od lat korzystam z odpowiedzi Adama. To powiedziawszy, że są przypadki, w których nie zachowuje się tak, jak się spodziewałem:

  1. gałęzie zawierające słowo „master” zostały zignorowane, np. „notmaster” lub „masterful”, a nie tylko gałąź master
  2. gałęzie zawierające słowo „dev” zostały zignorowane, np. „dev-test”, a nie tylko gałąź dev
  3. usuwanie gałęzi, które są osiągalne z HEAD bieżącej gałęzi (to znaczy niekoniecznie master)
  4. 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ą -fflagę:

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 --mergeddomyś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 --mergedma 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ą -fflagę. Domyślnym działaniem jest usuwanie tylko gałęzi, które zostały scalone w master, ale -fflaga 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).

Dlaczego musisz utworzyć funkcję? Nie jest git configatomowy?
VasiliNovikov

Aby poradzić sobie z opcjonalnym argumentem „-f” (jeśli dobrze rozumiem twoje pytanie)
eddies

1
ale jak to pomaga? Znaczy początek wyrazu !f(){ git branch .... To deklaracja funkcji, prawda? Dlaczego nie zacząć bezpośrednio od git branch ...?
VasiliNovikov

1
Masz całkowitą rację. Zredagowałem odpowiednio moją odpowiedź. Dzięki za wskaźnik!
eddies,

Czy poniższe czynności nie byłyby takie same jak w trybie bez użycia siły? git checkout master && git branch -d `git branch --merged` && git checkout - Tyle że to by usunęło develop, ale może to być prostsze podejście.
Guido Bouman,


18

Korzystanie z Git w wersji 2.5.0:

git branch -d `git branch --merged`

16
To może usunąć mastergałąź btw!
Wazery

4
Prawdziwe. Używam go tylko wtedy, gdy jestem pewien, że jestem włączony master.
drautb

11
git branch -d $(git branch --merged | grep -v master)
alexg

1
Jest to niebezpieczne, jeśli masz przepływ, wyobraź sobie, że masz master <- stage <- dev. Wciąż najprostsze rozwiązanie imo
Joseph Briggs

14

Możesz dodać zatwierdzenie do opcji --merged. W ten sposób możesz upewnić się, że usuwane są tylko gałęzie, które są scalone, tj. Origin / master

Następujące polecenie usunie scalone gałęzie z twojego źródła.

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 git push origin --delete 

Możesz sprawdzić, które gałęzie zostaną usunięte, zastępując początek git push - usuń za pomocą echa

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo

2
Podoba mi się opcja testu
iwein

12

Używam następującego skryptu Ruby, aby usunąć moje już połączone lokalne i zdalne gałęzie. Jeśli robię to dla repozytorium z wieloma pilotami i chcę tylko usunąć z jednego, po prostu dodaję instrukcję select do listy pilotów, aby uzyskać tylko te piloty, które chcę.

#!/usr/bin/env ruby

current_branch = `git symbolic-ref --short HEAD`.chomp
if current_branch != "master"
  if $?.exitstatus == 0
    puts "WARNING: You are on branch #{current_branch}, NOT master."
  else
    puts "WARNING: You are not on a branch"
  end
  puts
end

puts "Fetching merged branches..."
remote_branches= `git branch -r --merged`.
  split("\n").
  map(&:strip).
  reject {|b| b =~ /\/(#{current_branch}|master)/}

local_branches= `git branch --merged`.
  gsub(/^\* /, '').
  split("\n").
  map(&:strip).
  reject {|b| b =~ /(#{current_branch}|master)/}

if remote_branches.empty? && local_branches.empty?
  puts "No existing branches have been merged into #{current_branch}."
else
  puts "This will remove the following branches:"
  puts remote_branches.join("\n")
  puts local_branches.join("\n")
  puts "Proceed?"
  if gets =~ /^y/i
    remote_branches.each do |b|
      remote, branch = b.split(/\//)
      `git push #{remote} :#{branch}`
    end

    # Remove local branches
    `git branch -d #{local_branches.join(' ')}`
  else
    puts "No branches removed."
  end
end

Czy mógłbym ukraść ten smakołyk dla małej biblioteki pomocników git? github.com/yupiq/git-branch-util
Logan

1
Idź, nie umieszczałbym go tutaj, gdybym troszczył się o to, by ludzie w jakiś sposób ponownie
używali

@mmrobins Masz dodatkowe \/na początku instrukcji odrzucenia dla remote_brancheslinii. Czy to literówka, czy służy to celowi?
Jawwad

@mmrobins, och, nieważne widzę b.split(/\//)teraz linię
Jawwad

Jeśli chcesz to zrobić w zasadzie, ale za pomocą waniliowego basha zamiast ruby: stackoverflow.com/a/37999948/430128
Raman

11

Jak usunąć scalone gałęzie w konsoli PowerShell

git branch --merged | %{git branch -d $_.Trim()}

Jeśli chcesz wykluczyć nazwy główne lub dowolne inne gałęzie, możesz potokować za pomocą PowerShell Select-String w ten sposób i przekazać wynik do git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})

1
Wyższe odpowiedzi sugerują filtrowanie wzorca lub innych gałęzi. Dla tych, którzy chcą to zrobić w PowerShell: Git Branch - Scalony | findstr / v "master" | % {git branch -d $ _. trim ()}
tredzko

@tredzko Dobra uwaga. FTR wyższa odpowiedź to stackoverflow.com/questions/6127328/... - możesz ponownie opublikować swój komentarz z tym linkiem, a następnie usunę go
Ruben Bartelink

próbuje również usunąć * master:)
iesen

9

W odpowiedzi kuboon pominięto usuwanie gałęzi, które mają słowo master w nazwie gałęzi. Poniższe poprawia jego odpowiedź:

git branch -r --merged | grep -v "origin/master$" | sed 's/\s*origin\///' | xargs -n 1 git push --delete origin

Oczywiście nie usuwa samej gałęzi „master” :)


8

W Git nie ma polecenia, które zrobi to automatycznie. Ale możesz napisać skrypt, który używa poleceń Git, aby dać ci to, czego potrzebujesz. Można to zrobić na wiele sposobów, w zależności od używanego modelu rozgałęziania.

Jeśli chcesz wiedzieć, czy gałąź została scalona w master, poniższe polecenie nie przyniesie rezultatu, jeśli myTopicBranch został scalony (tzn. Możesz go usunąć)

$ git rev-list master | grep $(git rev-parse myTopicBranch)

Możesz użyć polecenia gałęzi Git i przeanalizować wszystkie gałęzie w Bash i wykonać forpętlę nad wszystkimi gałęziami. W tej pętli sprawdzasz za pomocą powyższego polecenia, czy możesz usunąć gałąź, czy nie.



7

Uwaga : Nie jestem zadowolony z poprzednich odpowiedzi (nie działa na wszystkich systemach, nie działa na zdalnie, nie określa - połączonej gałęzi, nie filtruje dokładnie). Dodaję własną odpowiedź.

Istnieją dwa główne przypadki:

Lokalny

Chcesz usunąć oddziały lokalne, które są już połączone z innym oddziałem lokalnym . Podczas usuwania chcesz zachować kilka ważnych gałęzi, takich jak master, develop itp.

git branch --format "%(refname:short)" --merged master | grep -E -v '^master$|^feature/develop$' | xargs -n 1 git branch -d

Uwagi :

  • git branch output --format „..” oznacza usunięcie białych znaków i umożliwienie dokładnego dopasowania grep
  • grep -Ejest używany zamiast egrep , więc działa również w systemach bez egrep (tj: git dla Windows).
  • grep -E -v '^master$|^feature/develop$' jest określenie lokalnych oddziałów, których nie chcę usuwać
  • xargs -n 1 git branch -d: wykonaj usuwanie lokalnych oddziałów (nie będzie działać dla zdalnych)
  • oczywiście pojawia się błąd, jeśli spróbujesz usunąć aktualnie wyrejestrowany oddział. Sugeruję więc, aby wcześniej przejść na master.

Zdalny

Chcesz usunąć zdalne gałęzie, które są już połączone z inną zdalną gałęzią . Podczas usuwania chcesz zachować niektóre ważne gałęzie, takie jak HEAD, master, wydania itp.

git branch -r --format "%(refname:short)" --merged origin/master | grep -E -v '^*HEAD$|^*/master$|^*release' | cut -d/ -f2- | xargs -n 1 git push --delete origin

Uwagi :

  • w przypadku zdalnego używamy tej -ropcji i podajemy pełną nazwę oddziału :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' jest dopasowanie zdalnych gałęzi, których nie chcemy usuwać.
  • cut -d/ -f2-: usuń niepotrzebny prefiks „origin /”, który w innym przypadku zostałby wydrukowany przez git branchpolecenie.
  • xargs -n 1 git push --delete origin : wykonaj usuwanie zdalnych gałęzi.

7

Jeśli korzystasz z systemu Windows, możesz użyć Windows Powershell lub Powershell 7 z Out-GridView, aby mieć ładną listę gałęzi i wybrać za pomocą myszy, który z nich chcesz usunąć:

git branch --format "%(refname:short)" --merged  | Out-GridView -PassThru | % { git branch -d $_ }

wprowadź opis zdjęcia tutaj po kliknięciu OK Powershell przekaże nazwy gałęzi, aby git branch -dje rozkazać i usunąć wprowadź opis zdjęcia tutaj


6

Możesz użyć git-del-br narzędzia .

git-del-br -a

Możesz go zainstalować za pippomocą

pip install git-del-br

PS: Jestem autorem narzędzia. Wszelkie sugestie / opinie są mile widziane.


1
@ stackoverflow.com/users/100297/martijn-pieters : Dlaczego ta odpowiedź została usunięta i odrzucona?
tusharmakkar08 29.09.16

1
Twoja odpowiedź i narzędzie nie działają. Spędzam nad tym kilka godzin. Nic.
SpoiledTechie.com,

@ SpoiledTechie.com: Czy możesz mi powiedzieć, z jakim dokładnie problemem masz do czynienia? Używam go regularnie.
tusharmakkar08

Mogę udostępnić zrzut ekranu, jeśli chcesz przełączyć go w tryb offline? spoiledtechie na ten mail google mail. :)
SpoiledTechie.com,

5

Jeśli chcesz usunąć wszystkie lokalne gałęzie, które są już połączone z gałęzią, w której aktualnie się znajdujesz, zaproponowałem bezpieczne polecenie, aby to zrobić, w oparciu o wcześniejsze odpowiedzi:

git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d

To polecenie nie wpłynie na twoją bieżącą gałąź ani gałąź główną. Powie ci też, co robi, zanim to zrobi, używając flagi -t xargs.



5

Używam schematu nazw eque git-flow, więc działa dla mnie bardzo bezpiecznie:

git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d

Zasadniczo szuka scalonych zatwierdzeń rozpoczynających się ciągiem znaków fix/lub feature/.


4

Spróbuj wykonać następujące polecenie:

git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Za pomocą git rev-parseuzyska aktualną nazwę oddziału w celu jej wykluczenia. Jeśli wystąpił błąd, oznacza to, że nie ma lokalnych oddziałów do usunięcia.

Aby zrobić to samo ze zdalnymi gałęziami (zmień originprzy pomocy nazwy zdalnej), spróbuj:

git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)

Jeśli masz wiele pilotów, dodaj grep origin |wcześniej, cutaby filtrować tylko origin.

Jeśli powyższe polecenie nie powiedzie się, spróbuj najpierw usunąć scalone gałęzie zdalnego śledzenia:

git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Następnie git fetchponownie git push -vduruchom pilota i ponownie użyj poprzedniego polecenia.

Jeśli często go używasz, rozważ dodanie jako ~/.gitconfigpliku aliasów .

Jeśli omyłkowo usunąłeś niektóre gałęzie, użyj, git reflogaby znaleźć utracone zatwierdzenia.


4

Na podstawie niektórych z tych odpowiedzi stworzyłem też własny skrypt Bash !

Używa git branch --mergedi, git branch -daby usunąć gałęzie, które zostały scalone, i monituje o każdą gałąź przed usunięciem.

merged_branches(){
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  for branch in $(git branch --merged | cut -c3-)
    do
      echo "Branch $branch is already merged into $current_branch."
      echo "Would you like to delete it? [Y]es/[N]o "
      read REPLY
      if [[ $REPLY =~ ^[Yy] ]]; then
        git branch -d $branch
      fi
  done
}

4

Poniższe zapytanie działa dla mnie

for branch in  `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print$1}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done

a to przefiltruje dowolną gałąź w rurze grep.

Działa dobrze na klonie HTTP, ale nie tak dobrze w przypadku połączenia ssh.


4

Od 2018.07

Dodaj to do [alias]sekcji swojego ~/.gitconfig:

sweep = !"f() { git branch --merged | egrep -v \"(^\\*|master|dev)\" || true | xargs git branch -d; }; f"

Teraz możesz po prostu zadzwonić, git sweepaby wykonać potrzebne czyszczenie.


Dla mnie wywołanie git sweep zawiera tylko te gałęzie, które powinny zostać oczyszczone, ale ich nie usuwa
Victor Moraes,

4

W systemie Windows z zainstalowanym programem git bash egrep -v nie będzie działać

git branch --merged | grep -E -v "(master|test|dev)" | xargs git branch -d

gdzie grep -E -vjest równoważne zegrep -v

Użyj -d, aby usunąć już połączone oddziały lub -Dusunąć niezłączonych oddziały


egrep -v działa dla mnie. Używam jednak gitbash z instalatora gitextension
Joe Phillips

4

Użyłem następującej metody, aby usunąć scalone lokalne ORAZ zdalne gałęzie w jednym cmd.

Mam w swoim bashrcpliku:

function rmb {
  current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
  if [ "$current_branch" != "master" ]; then
    echo "WARNING: You are on branch $current_branch, NOT master."
  fi
  echo "Fetching merged branches..."
  git remote prune origin
  remote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")
  local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")
  if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
    echo "No existing branches have been merged into $current_branch."
  else
    echo "This will remove the following branches:"
    if [ -n "$remote_branches" ]; then
      echo "$remote_branches"
    fi
    if [ -n "$local_branches" ]; then
      echo "$local_branches"
    fi
    read -p "Continue? (y/n): " -n 1 choice
    echo
    if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
      # Remove remote branches
      git push origin `git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$" | sed 's/origin\//:/g' | tr -d '\n'`
      # Remove local branches
      git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
    else
      echo "No branches removed."
    fi
  fi
}

oryginalne źródło

Nie usuwa to głównej gałęzi, ale usuwa scalone lokalne i zdalne gałęzie . Gdy masz już to w swoim pliku rc, po prostu uruchom rmb, zobaczysz listę połączonych gałęzi, które zostaną wyczyszczone i poprosisz o potwierdzenie akcji. Możesz zmodyfikować kod, aby nie prosił o potwierdzenie, ale prawdopodobnie dobrze jest go zachować.


3

Napisz skrypt, w którym Git sprawdzi wszystkie gałęzie, które zostały połączone w master.

Więc zrób git checkout master.

Na koniec usuń scalone gałęzie.

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git checkout $branchnew
done

git checkout master

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git push origin --delete $branchnew
done

3

Przyjęte rozwiązanie jest całkiem dobre, ale ma jeden problem polegający na tym, że usuwa również lokalne oddziały, które nie zostały jeszcze połączone w zdalne.

Jeśli spojrzysz na wynik, zobaczysz coś takiego

$ git branch --merged master -v
  api_doc                  3a05427 [gone] Start of describing the Java API
  bla                      52e080a Update wording.
  branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1
  initial_proposal         6e59fb0 [gone] Original proposal, converted to AsciiDoc.
  issue_248                be2ba3c Skip unit-for-type checking. This needs more work. (#254)
  master                   be2ba3c Skip unit-for-type checking. This needs more work. (#254)

Oddziały blai issue_248są oddziałami lokalnymi, które zostaną usunięte po cichu.

Ale możesz również zobaczyć słowo [gone], które wskazuje gałęzie, które zostały wypchnięte do pilota (który już nie ma), a tym samym oznacza, że ​​gałęzie można usunąć.

Pierwotną odpowiedź można zatem zmienić na (podzielony na wielowierszowy dla krótszej długości linii)

git branch --merged master -v | \
     grep  "\\[gone\\]" | \
     sed -e 's/^..//' -e 's/\S* .*//' | \
      xargs git branch -d

w celu ochrony jeszcze nie połączonych oddziałów. Również grepowanie dla mistrza, aby go chronić, nie jest potrzebne, ponieważ ma on pilota na początku i nie wyświetla się po jego zniknięciu.


3

Dla mnie git branch --mergednie pokazuje oddziałów, które zostały połączone za pośrednictwem GitHub PR. Nie jestem pewien powodów, ale używam następującego wiersza, aby usunąć wszystkie lokalne oddziały, które nie mają gałęzi zdalnego śledzenia :

diff <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | grep '<' | cut -c 3- | xargs git branch -D

Wyjaśnienie:

  • git branch --format "%(refname:short)" podaje listę lokalnych oddziałów
  • git branch -r | grep -v HEAD | cut -d/ -f2- daje listę zdalnych gałęzi, odfiltrowując HEAD
  • diff <(...) <(...) daje różnicę wyjściową dwóch poleceń w nawiasach
  • grep '<' filtruje gałęzie, które istnieją na pierwszej liście, ale nie na drugiej
  • cut -c 3- daje linię zaczynającą się od 3. znaku, usuwając w ten sposób prefiks <
  • xargs git branch -Dwykonuje się git branch -Ddla każdej nazwy oddziału

Alternatywnie możesz tego uniknąć grep -v '<':

diff --old-line-format="%L" --new-line-format="" --unchanged-line-format="" <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | xargs git branch -D
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.