Usuń lokalne gałęzie Git po usunięciu ich ze zdalnego repozytorium

162

Chcę, aby moje lokalne i zdalne repozytoria były zawsze zsynchronizowane pod względem oddziałów.

Po przejrzeniu pull requesta na GitHubie scalam i usuwam tam moją gałąź (zdalnie). Jak mogę pobrać te informacje z mojego lokalnego repozytorium i sprawić, by Git usunął również moją lokalną wersję gałęzi?

sf89
źródło
Czy chcesz usunąć swoje oddziały zdalnego śledzenia, oddziały lokalne czy jedno i drugie? W rzeczywistości możesz napisać alias (bash lub git), który zajmie wszystkie usunięte zdalne gałęzie i znajdzie lokalne kopie do usunięcia, wszystko w jednym poleceniu.
Może spróbuj użyć następujących poleceń, aby coś wymyślić, git ls-remotei git show-ref.
Możesz także sprawdzić git symbolic-refi git update-ref.
dzięki za pomoc, znalazłem odpowiedź gdzie indziej. Zobacz moją odpowiedź.
sf89
3
Możliwy duplikat Usuń gałęzie już nie na zdalnym
amaechler

Odpowiedzi:

180

Szybki sposób

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Uwaga: jeśli nie masz konta, może masterto spowodować usunięcie oddziału. Czytaj dalej, aby znaleźć „lepszy sposób”.

Upewnij się, że trzymamy mistrza

Możesz upewnić się, że masterani jakakolwiek inna gałąź nie zostanie usunięta przez grepdalsze. W takim przypadku poszedłbyś:

git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d

Więc jeśli chcemy zachować master, developa stagingna przykład pójdziemy:

git branch --merged | grep -v "\*" | grep -Ev "(\*|master|develop|staging)" | xargs -n 1 git branch -d

Uczyń to aliasem

Ponieważ jest trochę długi, możesz dodać alias do swojego .zshrclub .bashrc. Mój nazywa się gbpurge(dla git branches purge):

alias gbpurge='git branch --merged | grep -Ev "(\*|master|develop|staging)" | xargs -n 1 git branch -d'

Następnie załaduj ponownie .bashrclub .zshrc:

. ~/.bashrc

lub

. ~/.zshrc
sf89
źródło
Możesz umieścić polecenia w aliasie i uczynić je pojedynczym poleceniem. Jednak ponieważ branchjest to polecenie dotyczące porcelany, a nie hydrauliki , uważaj na wszelkie zmiany interfejsu użytkownika w przyszłych wersjach Git, które mogą go zepsuć.
1
Idealny! Zwróć uwagę, że zgodnie z przepływem pracy Github lokalny oddział masterzostanie usunięty.
Rubens Mariuzzo,
Nie, jestem pewien, że tam pozostaje (używam go codziennie i wydaje się, że tak nie jest).
sf89
4
Do Twojej wiadomości, jeśli chcesz zachować wiele oddziałów, możesz użyć jednego grepa, na przykład: grep -Ev '(\*|master|important-branch)'
Andrew Burns
4
Jeśli ~/.gitconfigzamiast tego chcesz umieścić to w swoim , dodaj do [alias]sekcji: gbpurge = !"git branch --merged | grep -Ev '\\*|master|develop|staging' | xargs -n 1 git branch -d"(nie ma potrzeby używania () w wyrażeniu grep).
dskrvk
82

Używam tego samego przepływu z GitHubem i nie znalazłem poprzednich odpowiedzi satysfakcjonujących mnie, ponieważ git branch --mergedzawiera listę gałęzi, które zostały scalone, ale nie wszystkie zostały usunięte zdalnie w moim przypadku. Więc to zadziałało dla mnie:

git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d

gdzie:

  • git fetch --all -p: aktualizacja statusu oddziałów lokalnych
  • git branch -vv: wyświetla stan oddziałów lokalnych
  • grep ": gone]": filtruj usunięte
  • awk '{ print $1 }': wyodrębnij ich nazwy
  • xargs -n 1 git branch -d: przekazuje nazwę do polecenia usuwania

Uwaga: jeśli wolisz, możesz użyć -D zamiast -d, co wymusza usuwanie.

Na przykład:

someUsr@someHost:~/repo$ git branch -a
basic-testing
integration-for-tests
* master
origin
playground-for-tests
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

someUsr@someHost:~/repo$ git fetch --all -p; git branch -vv | grep ": gone]" | awk '{ print $1 }' | xargs -n 1 git branch -d
Fetching origin
Deleted branch integration-for-tests (was fbc609a).
Deleted branch playground-for-tests (was 584b900).

someUsr@someHost:~/repo$ git branch -a
basic-testing
* master
origin
test-services
remotes/origin/HEAD -> origin/master
remotes/origin/basic-testing
remotes/origin/master
remotes/origin/test-services

Odniesienie:

http://git-scm.com/book/en/v2/Git-Branching-Remote-Branches

Alessio
źródło
3
Pozwoliłem sobie na to, aby zawsze robić to przeciwko mistrzowi, dlatego: git checkout master; git pull origin master; git fetch --all -p; git branch -vv | grep gone | awk '{ print $1 }' | xargs -n 1 git branch -d Świetny scenariusz i wyjaśnienie, dziękuję za to :)
Miguelgraz
Zauważ, że branch -vvpokazuje ostatni komunikat o zatwierdzeniu z gałęzi. Jeśli zdarzyło ci się „odejść” w tej wiadomości grep gone, trafiłoby to również w tę gałąź. Więc grep ": gone]"prawdopodobnie jest trochę bezpieczniejszy w użyciu.
chawkinsuf
1
To jest właściwa odpowiedź na to pytanie. Dziękuję Ci.
Andrei Gladkyi,
1
Jeszcze lepiej:awk '$3 $4 ~ /:gone]$/ { print $1 }'
Jakub Bochenski
3
Oprócz potrzeby -Dzamiast -dtego jest to idealna odpowiedź!
Cas
72

próbować:

git pull --prune

który usuwa twój lokalny oddział, jeśli odpowiadający mu zdalny oddział zostanie usunięty.

Zaktualizowano:

Powyższe stwierdzenie nie jest tak poprawne.

W rzeczywistości uruchomienie git pull --prunespowoduje tylko USUNIĘCIE gałęzi zdalnego śledzenia takie jak

zdalne / pochodzenie / fff
piloty / pochodzenie / dev
piloty / pochodzenie / mistrz

Następnie możesz uruchomić, git branch -raby sprawdzić gałęzie zdalnego śledzenia pozostawione na twoim komputerze. Załóżmy, że lewe gałęzie to:

pochodzenie / dev
pochodzenie / mistrz

co oznacza, że ​​oddział origin/fffzostał usunięty.

Więc po bieganiu po git pull --pruneprostu uruchom:

git branch --merged | grep -vFf <(git branch -r | cut -d'/' -f2-)

możesz znaleźć wszystkie lokalne oddziały, które:

  1. nie mają już odpowiednich oddziałów zdalnych;
  2. można bezpiecznie usunąć.

następnie <the command above> | xargs git branch -dmoże usunąć je wszystkie.

nicky_zs
źródło
42
Ta odpowiedź nie jest do końca poprawna. --pruneFlag usunie tylko zdalne śledzenie oddziałów, a nie lokalne oddziały.
3
Zgadzam się z @Cupcake tutaj, to nie zapewnia tego, czego tutaj szukam.
sf89
6
Nie zamierzam głosować za, ale tego właśnie potrzebowałem po usunięciu lokalnych oddziałów, a następnie usunięciu z GitHub, ale nadal istnieją jako piloty w moim poleceniu git remote -v.
Przemówienie
8
Możesz też to zrobić git fetch --prune, to mój sposób wyboru
e_m0ney
1
Kolejny błąd Gita wynikający z porady znalezionej przy przepełnieniu stosu ... git pull --prunespowodował, że „Poprosiłeś o ściągnięcie ze zdalnego '--prune', ale nie określiłeś gałęzi. Ponieważ nie jest to domyślny zdalny skonfigurowany dla Twojej bieżącej gałęzi, musi określić gałąź w wierszu poleceń. "
jww
23

Powinno to zadziałać, aby uniknąć usunięcia gałęzi głównej i deweloperskiej z zaakceptowanym rozwiązaniem:

git branch --merged | egrep -v "^\*|master|development" | xargs -n 1 git branch -d
Nieustraszony
źródło
16

Dla osób używających PowerShell jest to odpowiednik powyższej odpowiedzi :

git branch -vv | Select-String -Pattern ': gone]' | ForEach-Object{($_ -split "\s+")[1]} | %{ git branch -D $_ }
  1. Filtruj wszystkie gałęzie, które są oznaczone jako nieobecne
  2. Wezwij git branch -Dkażdą ze znalezionych gałęzi
amaechler
źródło
6

Nic z tego nie działało dla mnie. Możesz zobaczyć moją drugą odpowiedź tutaj: https://stackoverflow.com/a/34969726/550454

Ale zasadniczo mam teraz to w moim ~/.gitconfig:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d
Karl Wilbur
źródło
5

Bardzo proste rozwiązanie: usuń lokalne repozytorium i ponownie sklonuj zdalne. Może nie wydawać się zbyt eleganckie, ale jest proste i dokładnie zrozumiesz, co robisz, nie czytając stron podręcznika :-).


źródło
1
Po co tyle głosów przeciw? Mam na myśli oczywiście nieefektywne, szczególnie w przypadku większych repozytoriów, ale robi to, o co prosił OP. Czy jest jakiś inny powód, aby tego nie robić?
3ocen
6
Ponieważ stracisz wszystkie lokalne oddziały, skrytki, niezabezpieczone commity ... to jak łowienie dynamitu.
sevenseacat
1
To samo dzieje się, gdy laptop, na którym pracujesz, zostanie w jakiś sposób uszkodzony, zgubiony lub skradziony, więc zwykle nie przechowuję niczego kluczowego lokalnie. Wydaje mi się, że lepiej jest po prostu utworzyć gałąź i wypchnąć ją, nawet w przypadku małych funkcji, i usunąć ją, gdy nie jest już przydatna.
1

Napisałem tę jedną linijkę, aby wyświetlić wszystkie lokalne oddziały, które nie mają odpowiedniego oddziału zdalnego:

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -

Po wykonaniu tej czynności usunięcie tych lokalnych oddziałów jest łatwe dzięki xargs :

diff -u <(git branch|sed 's/..//') <(git branch -r|sed 's/..origin\///')|tail -n +4|sed -n "s/^-//p" -|xargs -r git branch -d
ks1322
źródło
to masterteż mnie wymienia , nie działa zgodnie z oczekiwaniami; uważaj
Enrico
1

Robię to po prostu, aby usunąć połączone oddziały lokalne:

git branch -d $(git branch --merged)

a jeśli chcesz usunąć również nieistniejące śledzenia:

git pull --prune
alacambra
źródło
1

W przypadku, gdy właśnie wypchnąłeś i scaliłeś swoją gałąź do mastera, wykonaj następujące czynności w git bash:

git branch -d branch_name_to_delete

Jeśli jesteś obecnie w tej gałęzi, odepchnie cię to z powrotem do mastera. W tym momencie wykonaj pociągnięcie

git pull
Joshua Schlichting
źródło
-2

Głosowana odpowiedź ma potencjał usunięcia wzorca. Rozważ poniższy praktyczny przykład.

Miałem dwie gałęzie funkcji hemen_README i hemen_BASEBOX, które zostały połączone w develop, a następnie develop w master. Gałęzie funkcji hemen_README i hemen_BASEBOX zostały usunięte zdalnie, ale nadal były widoczne lokalnie. Nie jestem też lokalnie mistrzem, ale rozwijam się.

W tym wypadku

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                      671ad6c Merged in hemen_README (pull request #1)
        hemen_BASEBOX                a535c0f added global exec paths to puppet manifest
        hemen_README                 ba87489 Updated Readme with considerable details
        master                       8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop       671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/hemen_BASEBOX a535c0f added global exec paths to puppet manifest
        remotes/origin/hemen_README  ba87489 Updated Readme with considerable details
        remotes/origin/master        2f093ce Merged in develop (pull request #3)

Więc jeśli uruchomię powyższe częściowe polecenie

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch --merged | grep -v "\*"
        hemen_BASEBOX
        hemen_README
        master

Zwróć uwagę, że pokazuje również master, który ostatecznie zostanie usunięty.

W każdym razie udało mi się to zrobić. Dzielę się z wami moim dziennikiem sesji, w jaki sposób to osiągnąłem.

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin --dry-run
    Pruning origin
    URL: [email protected]:hemenkapadiapublic/vagrant-webdev.git
     * [would prune] origin/hemen_BASEBOX
     * [would prune] origin/hemen_README
    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git remote prune origin 
    Pruning origin
    URL: [email protected]:hemenkapadiapublic/vagrant-webdev.git
     * [pruned] origin/hemen_BASEBOX
     * [pruned] origin/hemen_README

Właśnie sprawdziłem, co będzie przycinane, a potem je przycinam. patrząc na polecenie oddziału poniżej, zajęliśmy się pilotami

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                671ad6c Merged in hemen_README (pull request #1)
        hemen_BASEBOX          a535c0f added global exec paths to puppet manifest
        hemen_README           ba87489 Updated Readme with considerable details
        master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/master  2f093ce Merged in develop (pull request #3)

Teraz idź dalej i usuń lokalne oddziały

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_BASEBOX 
    Deleted branch hemen_BASEBOX (was a535c0f).
    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -d hemen_README
    Deleted branch hemen_README (was ba87489).

Teraz dobrze, gałęzie są zgodne z życzeniem.

    hemen@hemen-MXC061:~/data/projects/vagrant-webdev$ git branch -v -a
    * develop                671ad6c Merged in hemen_README (pull request #1)
        master                 8980894 [behind 7] Initial Vagrantfile, works for vagrant up. Also initial .gitignore
        remotes/origin/develop 671ad6c Merged in hemen_README (pull request #1)
        remotes/origin/master  2f093ce Merged in develop (pull request #3)
Hemen Kapadia
źródło
Oczywiście ma możliwość usunięcia wzorca. Przeczytaj uważnie pytanie. Jak powiedziałem, potrzebowałem sposobu, aby uporządkować rzeczy w moim lokalnym. Oznacza to usunięcie wszystkich gałęzi, które już nie istnieją na zdalnym serwerze. Jeśli mastera już tam nie ma, zniknie on również na twoim lokalnym komputerze.
sf89