İzleme dallarını artık uzaktan kumandada kaldırmayın


1172

Uzak eşdeğeri artık mevcut olmayan tüm izleme dallarını silmenin basit bir yolu var mı?

Misal:

Şubeler (yerel ve uzak)

  • usta
  • köken / ana
  • köken / hata düzeltme-a
  • köken / hata düzeltme-b
  • köken / hata-düzeltme-C

Yerel olarak, sadece bir ana dalım var. Şimdi bug-fix-a üzerinde çalışmam gerekiyor , bu yüzden kontrol ediyorum, üzerinde çalışıyorum ve uzaktan kumandadaki değişiklikleri itiyorum. Sonra ben bug-fix-b ile aynısını yaparım .

Şubeler (yerel ve uzak)

  • usta
  • hata düzeltme-a
  • hata düzeltme-b
  • köken / ana
  • köken / hata düzeltme-a
  • köken / hata düzeltme-b
  • köken / hata-düzeltme-C

Şimdi yerel şubeler ustası , hata-düzeltme-a , hata-düzeltme-b var . Master şube yöneticisi değişikliklerimi master'a birleştirecek ve birleştirmiş olduğu tüm dalları silecektir.

Şimdi şu anki durum:

Şubeler (yerel ve uzak)

  • usta
  • hata düzeltme-a
  • hata düzeltme-b
  • köken / ana
  • köken / hata-düzeltme-C

Şimdi dalları silmek için bazı komutlar çağırmak istiyorum (bu durumda bug-fix-a , bug-fix-b artık uzak depoda temsil ) .

Mevcut komut gibi bir şey olurdu git remote prune origin, ama daha çok git local prune origin.

Yanıtlar:


1282

git remote prune origin uzaktan kumandada olmayan dalları izleme kuru erik.

git branch --merged Geçerli dalda birleştirilen dalları listeler.

xargs git branch -d standart girdide listelenen dalları siler.

Tarafından listelenen şubeleri silerken dikkatli olun git branch --merged. Liste master, silmemeyi tercih ettiğiniz diğer dalları içerebilir .

Şubeleri silmeden önce kendinize listeyi düzenleme fırsatı vermek için aşağıdakileri tek bir satırda yapabilirsiniz:

git branch --merged >/tmp/merged-branches && \
  vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

17
Birleştirilmiş dalların ilk satırı * masterbenim sistemimde. Aşağıdaki komut benim için çalıştı:git branch -d $(git branch --merged |tail -n +2)
Trendfischer

99
Eğer ben developo zaman git branch --mergediçerir master! Muhtemelen (kesinlikle!) Bunu silmek istemezsiniz. Ayrıca git branch -dküçük harf -d"güvenli silme" anlamına gelmesi gerektiğini düşünüyorum sadece örneğin birleştirilmiş ise sil.
thom_nic

11
Orada geliştirilmiş bir çözüm var gibi görünüyor .
Sergey Brunov

34
Birleştirilmiş kaldırılması yararlıdır, ancak "uzaktan kumandada olmayan dalları kaldır" ile aynı değildir.
dlsso

11
git branch --merged | grep -v "master" >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
Ustayı

590

Komuttan sonra

git fetch -p

çalıştırdığınızda uzak referansları kaldırır

git branch -vv

uzak durum olarak "gitti" i gösterir. Örneğin,

$ git branch -vv
  master                 b900de9 [origin/master: behind 4] Fixed bug
  release/v3.8           fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
  release/v3.9           0d680d0 [origin/release/v3.9: behind 2] Updated comments
  bug/1234               57379e4 [origin/bug/1234: gone] Fixed bug

Böylece, uzaktan kumandaya geçmiş yerel şubeleri kaldırmak için basit bir komut dosyası yazabilirsiniz:

git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done

Yukarıdakilerin git branchyukarı akış durumunu elde etmek için "porselen" komutunu kullandığını unutmayın .

Bu durumu elde etmenin başka bir yolu da , yukarıdaki gibi olacak olan git for-each-refenterpolasyon değişkeniyle "tesisat" komutunu kullanmaktır .%(upstream:track)[gone]

Bu yaklaşım biraz daha güvenlidir, çünkü taahhüt mesajının bir kısmında yanlışlıkla eşleşme riski yoktur.

git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}'); do git branch -D $branch; done

8
@KrzysztofWende - Solaris ve bazı BSD'ler ve bazı OS X'de değil
jww

4
Görünüşe göre bu, son işlem mesajında ​​"gitmiş" tüm şubeleri de kaldıracaktır.
dlsso

11
@dlsso Son tamamlama mesajı ": gone]" dizesini içeriyorsa, evet de kaldırılır. Taahhüt mesajını kaldırmak için ek bir awk / gawk ile basitlik pahasına daha sağlam hale getirebilirsiniz. git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
jason.rickman

2
Önceki yorumuma (soru) yanıt olarak, mevcut dalın ilk alanı * olarak var. "Gitti" dalları listesinde de varsa, $ 1 atanır * ve awk dosya ve klasör adlarını tüküren bir dosya dosyası olarak yorumlanır. Ben grep ifadesini elimine ve filtreleme her şeyi awk vardı: awk '/: gone]/{if ($1!="*") print $1}'. Bu şimdi beklendiği gibi çalışıyor.
rhaben

5
Komut tek tırnak kullandığından @ahmedbhs 'tamamını komutunu surround çift tırnak "kullanmak gerekir Ayrıca, (bunun gibi) kabuk komutlardır gerektiren git adlar başında benim için bu işler.!.test = "!git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
jason.rickman

306

Bu cevapların çoğu aslında asıl soruya cevap vermiyor. Ben kazma bir demet yaptım ve bu buldum en temiz çözüm oldu. İşte bu cevabın biraz daha kapsamlı bir versiyonu:

  1. Varsayılan şubenizi kontrol edin. Geneldegit checkout master
  2. Çalıştırmak git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

Açıklama:

İzleme dallarınızı budanarak ve sonra "gittiğini" gösteren yerel olanları silerek çalışır git branch -vv.

Notlar:

Diliniz İngilizce dışında bir dile ayarlanmışsa gone, uygun kelimeye geçmeniz gerekir . Yalnızca yerel şubelere dokunulmaz. Uzaktan kumandadan silinen ancak birleştirilmeyen şubeler bir bildirim gösterir ancak yerel olarak silinmez. O silmek isterseniz de değiştirmek -diçin -D.


2
fransız OS gitti için disparue tarafından değiştirilmelidir
Mohamed EL HABIB

4
ingilizce zorlamak için git şubesinden önce LANG = en_US eklemelisiniz: git fetch --prune && LANG = en_US git branch -vv | awk '/: gitti] / {print $ 1}' | xargs git branch -d
Mohamed EL HABIB

3
Ben eklemek istiyorum git checkout master && ...komutun başında.
iarroyo

2
Silinmesi gereken bir dalda olduğunuzda bu tehlikelidir - bu durumda ilk sütun daha sonra xargs'a iletilen '*' olur. Bunu iyileştirmek için, çıktıyı awk'ye geçirmeden önce '*' karakterini ekleyin: sed -e 's / ^ * //'
meeee

6
Dikkatli! Tüm yerel şubelerinizin silinmesine neden olacak bir kenar durum vardır: Şu anda uzaktan kumandada silinmiş bir şubedeyseniz, çıktısı git branch -vvyürütme ile sonuçlanacak bir yıldız işareti ile başlayacaktır git branch -d *. İşte yıldız işaretli satırları yoksayacak yamalı bir sürüm:git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
kcm

210

Normalde zaten 16 cevabı olan bir soruya cevap vermezdim, ancak diğer tüm cevaplar yanlış ve doğru cevap çok basit. Soru, "Uzak eşdeğeri artık mevcut olmayan tüm izleme dallarını silmenin basit bir yolu var mı?"

"Basit", kırılgan değil, tehlikeli değil ve tüm okuyucuların sahip olmayacağı araçlara güvenmeksizin hepsini bir seferde silmek anlamına geliyorsa, doğru cevap: hayır.

Bazı cevaplar basit, ama sorulan şeyi yapmıyorlar. Diğerleri sorulanları yapar, ancak basit değildir: hepsi Git çıktısını metin işleme komutları veya her sistemde bulunmayan komut dosyası dilleri aracılığıyla ayrıştırmaya dayanır. Bunun da ötesinde, önerilerin çoğu çıktısı komut dosyası tarafından ayrıştırılmak üzere tasarlanmamış porselen komutlarını kullanır ("porselen", insanın çalışması için amaçlanan komutları ifade eder; komut dosyaları, alt düzey "tesisat" komutlarını kullanmalıdır).

Daha fazla okuma:


Bunu güvenli bir şekilde yapmak istiyorsanız, sorudaki kullanım durumunda (sunucuda silinmiş ancak yerel şubeler olarak var olan çöp toplama izleme dalları) ve yalnızca yüksek düzey Git komutlarıyla

  • git fetch --prune(veya git fetch -pbu bir takma addır veya git prune remote origingetirmeden aynı şeyi yapar ve çoğu zaman istediğiniz şey değildir).
  • Silindi olarak bildirilen uzak dalları not alın. Veya daha sonra bulmak için git branch -v(artık herhangi bir yetim izleme dalı "[gitti]" olarak işaretlenir).
  • git branch -d [branch_name] her yetim takip şubesinde

(diğer bazı cevapların önerdiği şey budur).

Bir çözüm yazmak istiyorsanız, o zaman for-each-refbaşlangıç ​​noktanız, burada Mark Longair'in cevabı ve başka bir sorunun cevabı gibi , ancak bir kabuk komut dosyası döngüsü yazmadan veya xargs veya başka bir şey kullanmadan bunu kullanmanın bir yolunu göremiyorum .


Arka plan açıklaması

Neler olduğunu anlamak için, şubeleri izleme durumunda bir şubeniz değil, üç şubeniz olduğunu takdir etmeniz gerekir. (Ve hatırlayın "şube" sadece bir taahhüt bir işaretçi anlamına gelir.)

Bir izleme dalı verildiğinde feature/X, uzak depoda (sunucu) bu dal bulunacak ve çağrılacaktır feature/X. Yerel deponuzda remotes/origin/feature/X"Uzaktan kumandanın bana özelliği / X dalı olduğunu, en son konuştuğumuz şey" dediğimiz bir şube var ve son olarak yerel deponun feature/Xen son taahhüdünüzü gösteren ve "parça" remotes/origin/feature/X, yani onları hizalamak için çekip itebilirsiniz.

Bir noktada, birisi feature/Xuzaktan kumandadaki sildi . O andan itibaren, yerelinizle kalırsınız feature/X(muhtemelen daha fazla istemezsiniz, X özelliği üzerindeki çalışmalar muhtemelen bittiğinden) ve remotes/origin/feature/Xkesinlikle işe yaramaz çünkü tek amacı sunucunun şubesinin durumunu hatırlamaktı .

Git yedeklemeyi otomatik olarak temizlemenize izin verir remotes/origin/feature/X- bu da işe git fetch --pruneyarar - ancak bir nedenden ötürü kendiniz otomatik olarak silmenize izin vermez feature/X... feature/Xhala yetim izleme bilgilerinizi içermesine rağmen, tamamen birleştirilen eski izleme dallarını belirlemek için. (Sonuçta, verebilir size elle kendiniz tarafından operasyon yapalım bilgileri.)


3
Bu çok daha güvenli bir cevap. Ayrıca, seçilen yanıtın aksine bir "Squash and Merge" iş akışı kullanırsanız çalışır.
Jake Levitt

3
Bu gerçekten sadece "nasıl gitti dalları" (ve 2015 yılında zaten jason.rickman tarafından gönderilen aynı komut ile) sorunun kolay kısmı cevap ama daha sonra OP tam olarak ne olduğunu tüm dalları silmenizi söyler yapmak istemiyor.
Voo

4
@Voo Cevabın amacı budur: nasıl yapılacağını söylemek değil (bu sadece bir bonus) ama cevabın bunu yapmanın kolay ve basit bir yolu olmadığıdır. Hangi soruya formüle edildiği gibi doğru cevaptır.
Andrew Spencer

1
"Bunu güvenli bir şekilde yapmak istiyorsanız, söz konusu kullanım durumunda .." - ilk paragrafın çoğu iddialarını reddeder. "[Git] işlemi kendiniz elle yapmanızı sağlayan bilgileri verebilir" - biz programcıyız, bu yüzden bilgi liste halinde verildiğinde (gösterilen) görev hala basittir (örn. xargs). Ayrıca git aliasbir dizi vakayı basitleştirmek de vardır .
user2864740

2
@ user2864740 Bazı okuyucular, küçük bir bash betiği yazmanın "basit" tanımına girdiğini düşünebilir ve bu tamamen savunulabilir bir konumdur, ancak 2. paragrafta kendi "basit" yorumumu verdim ve cevabın geri kalanı tutarlı Bununla birlikte. Kuşkusuz kısıtlayıcı yorumumu savunmak için, tüm Git kullanıcıları xargsveya bash değil ve muhtemelen burada bir mikro kodlama zorluğu aramıyorlar, hızlı bir cevap kadar, gerçek hedeflerinden uzaklaşmadan güvenli bir şekilde başvurabilirler. .
Andrew Spencer

52

Cevabı burada buldum: Birleştirilen tüm git dallarını nasıl silebilirim?

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

Usta olduğumuzdan emin ol

İlkinden sonra masterbaşka bir şube ekleyerek bu konunun veya herhangi bir dalın kaldırılmamasını sağlayabilirsiniz grep. Bu durumda:

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

Yani eğer biz tutmak istedi master, developve stagingörneğin giderdik:

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

Bunu bir takma ad yap

Biraz uzun olduğu için .zshrcveya cihazınıza bir takma ad eklemek isteyebilirsiniz .bashrc. Benimki gbpurge(için git branches purge):

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

Sonra yeniden sizin .bashrcveya .zshrc:

. ~/.bashrc

veya

. ~/.zshrc

8
Faydalı, ama aynı değil "uzaktan değil dalları kaldırmak"
dlsso

Greate answer @karlingen, bunu tüm geliştirme ortamlarımda kalıcı olarak gbpurge olarak görüyorum
Peter Dolan

50

Windows Çözümü

Microsoft Windows Powershell için:

git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}

Açıklama

git checkout master ana şubeye geçer

git remote update origin --prune kuru erik uzak dalları

git branch -vvtüm dalların ayrıntılı çıktısını alır ( git başvurusu )

Select-String -Pattern ": gone]" yalnızca uzaktan kumandadan kaldırıldıkları kayıtları alır.

% { $_.toString().Trim().Split(" ")[0]} şube adını al

% {git branch -d $_} şubeyi siler


3
Bunun için teşekkürler, yine de şube adından önce iki boşluk kaldırmak için bir .Trim()sonra eklemek zorunda kaldı .toString().
Matthew

2
Bu komut için teşekkürler. Ben değiştirmek git branch -dzorunda git branch -Dbaşka şube tam birleştirilmiş değil hatası alıyorum.
markieo

1
@markieo Muhtemelen bunu biliyorum, ama başkası için - git branch -Dbir yıkıcı ve henüz itti değil yerel çalışmayı silecektir. -dher zaman güvenlidir, sadece dikkatli olun -D.
Nate Barbettini

33

Diğer çözümlerin çoğunda "gitti" için kullanılan desen benim için biraz korkutucuydu. Daha güvenli olmak için, --formather dalın yukarı akış izleme durumunu çıkarmak için bayrağı kullanır .

Windows dostu bir sürüme ihtiyacım vardı, bu yüzden bu Powershell kullanarak "gitti" olarak listelenen tüm dalları siler:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }

İlk satır, yukarı yönlü dalı "gitmiş" yerel şubelerin adını listeler. Bir sonraki satır boş satırları ("gitmemiş" dallar için çıktı olarak) kaldırır, dal adını dal silme komutuna iletilir.


6
--formatSeçenek oldukça yeni gibi görünüyor; Git için 2.10.something 2.16.3 için yükseltme gerekiyordu. Bu Linux-imsi sistemler için benim değişikliktir:git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
bxm

2
Bu şimdiye kadarki en iyi çözüm. Bir öneri kullanmaktır refname:short. Sonra satırı silebilirsiniz% { $_ -replace '^refs/heads/', '' }
ioudas

2
Bu pencereler için harika bir çözümdür. Ben daha okunabilir neden bu gibi kullanıyorum git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ }Ayrıca muhtemelen -dyerine kullanmak için iyi bir fikir -D. Artık uzaktan kumandada olmayan dallar için zorla silmeye gerek yoktur.
Rubanov

31

Master ile birleştirilen tüm dalları kaldırın, ancak master'ın kendisini kaldırmaya çalışmayın:

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

veya takma ad ekleyin:

alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"

Açıklama:

git checkout master ödeme ana şubesi

git pull origin master yerel şubenin tüm uzaktan değişikliklerin birleştirildiğinden emin olun

git fetch -p silinmiş uzak dallara yapılan referansları kaldır

git branch -d $(git branch master --merged | grep master -v) master ile birleştirilen tüm dalları sil, ancak master'ın kendisini kaldırmaya çalışma


3
Bir not, bu çok yardımcı olur, ancak uzaktan kumandaya hiç itilmemiş dalları da kaldıracaktır. Sadece farklılıkları listelemek ve daha sonra gerçekten silmek istediğiniz şeyi git branch -Dkomuta kopyalamak daha güvenlidir
Zefiryn

Sadece açıklığa kavuşturmak için Zefiryn, tek astarın bir parçası olmayan -D seçeneğini kullanmaya atıfta bulunuyor.
cs01

1
Veya git branch -ditilmemiş dallar hakkında bir uyarı vermesi gereken küçük harfle juse yapın .
acme

16
git fetch -p

Bu, artık uzaktan kumandada bulunmayan dalları budaır .


64
bu uzak referansları kaldırır, ancak yerel şubeleri kendileri kaldırmaz. Yararlı bir komut olsa da, bunun OP'nin sorusuna cevap verdiğini sanmıyorum.
thataustin

Ne? Bu benim için yerel şubeleri siler.
Alex Hall

1
@AlexHall Uzak deponun bir dalı vardır X; siz git checkout X; artık deponuzda (yerel) bir izleme dalı Xve uzak bir şube var origin/X; uzak depo silinir X; siz git fetch-p; yerel deponuzda, sadece origin/Xdeğil, aynı zamanda Xsilinmiştir. Söylediğin bu mu?
Andrew Spencer

16

Yığın için yine başka bir cevap, Patrick'in cevabından ağır bir şekilde çekiliyor (ki bu hoşuma gidiyor, çünkü bu gone],git branch çıktının ) ama bir * nix bükülmüş.

En basit haliyle:

git branch --list --format \
  "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" \
  | xargs git branch -D

Bu git-gonebenim yolumda bir komut dosyası sarılmış var :

#!/usr/bin/env bash

action() {
  ${DELETE} && xargs git branch -D || cat
}

get_gone() {
  git branch --list --format \
    "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)"
}

main() {
  DELETE=false
  while [ $# -gt 0 ] ; do
    case "${1}" in
      (-[dD] | --delete) DELETE=true ;;
    esac
    shift
  done
  get_gone | action
}

main "${@}"

Not - --formatSeçenek oldukça yeni gibi görünüyor; Git için 2.10.something 2.16.3 için yükseltme gerekiyordu.

DÜZENLEME: yaklaşık önerinizden tweaked refname:shortgelen Benjamin W.

NB2 - Ben sadece test bash, bu nedenle hashbang, ama muhtemelen taşınabilir sh.


İlk satırda sedkullanarak bölümü atlayamaz %(refname:short)mısınız?
Benjamin W.

Benim için çalışıyor gibi görünüyor ve şimdi temiz bir Git takma adı olarak var - burada hepsinin en temiz çözümü!
Benjamin W.

2.13 tanıtıldı --format. Parçayı atlamanın başka bir yolu sedda kullanmaktır git update-ref -d. Bunun muhtemelen biraz güvensiz olduğuna dikkat edin, git for-each-refburada kullanmak daha güvenlidir (verilir --shell).
gsnedders

Harika bir cevap, ve bunu --formatkendim yapmak için akın ettiğimde kendi sorularıma cevap vermeme yardımcı oldu . Sadece bir soru: neden #!bash? Buradaki her şey shbenim için taşınabilir görünüyor .
Toby Speight

Bu benim normal kazanım ve başka bir yerde test etmemiştim.
bxm

15

Master hariç tüm yerel şubeleri temizlemek için bazı basit satırlar için yararlı olabilir

git branch | grep -v "master" | grep -v "develop" | xargs git branch -D

Müthiş cevap! 'git branch | grep -v "master" | grep -v "develop"Komutun silme kısmına eklemeden önce bu tür şeylerle nasıl kolayca oynayabileceğimi seviyorum . Mar😊
finneycanhelp

Ancak bu yukarıdaki soruya cevap vermiyor. Uzaktan kumanda hala orada olsa bile bu, dalları siler.
Jim.B

13

Bu, yerel ana başvuru ve şu anda kullanılmakta olan dışındaki tüm birleştirilmiş yerel dalları silecektir:

git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d

Bu işlem, " origin " tarafından referans verilen uzak depodan zaten kaldırılmış olan tüm dalları siler , ancak yine de " uzaktan kumandalar / origin " içinde yerel olarak kullanılabilir durumdadır .

git remote prune origin

git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d Açıklama: Ben yerine tercih git branch --mergedtarafından git branch -vvönceki çünkü durumu (gitti) göstermek için git branch --mergedde ana gösterebilir
jpmottin

13

Bunu yapmak için yerleşik bir komut olduğunu düşünmüyorum, ancak aşağıdakileri yapmak güvenlidir:

git checkout master
git branch -d bug-fix-a

Kullandığınızda -dgit, tamamen birleştirilmedikçe HEADveya yukarı akış uzaktan izleme şubesine gitmediği sürece şubeyi silmeyi reddeder . Yani, her zaman her çıktı için döngü git for-each-refve her dalı silmeye çalışabilirsiniz. Bu yaklaşımla ilgili sorun, muhtemelen geçmişini içerdiği bug-fix-diçin silinmek istemediğinizden şüphelenmem origin/bug-fix-d. Bunun yerine, aşağıdaki gibi bir komut dosyası oluşturabilirsiniz:

#!/bin/sh

git checkout master &&
for r in $(git for-each-ref refs/heads --format='%(refname:short)')
do
  if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ]
  then
    if [ "$r" != "master" ]
    then
      git branch -d "$r"
    fi
  fi
done

Uyarı: Bu komut dosyasını test etmedim - sadece dikkatli kullanın ...


Senaryoyu düzenleme özgürlüğünü aldım. Hala garanti vermeyecek, ama şimdi çalışıyor ve çalışıyor gibi görünüyor.
fwielstra

13

TL; DR:

Uzakta olmayan TÜM yerel dalları kaldırın

git fetch -p && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D

Uzakta olmayan VE tamamen birleştirilen VE daha önce birçok yanıtta belirtildiği gibi kullanılmayan TÜM yerel dalları kaldırın .

git fetch -p && git branch --merged | grep -v '*' | grep -v 'master' | xargs git branch -d

açıklama

  • git fetch -p uzaktan kumandada artık mevcut olmayan tüm dalları budaır
  • git branch -vv yerel şubeleri yazdıracak ve budanmış şube ile etiketlenecek gone
  • grep ': gone]' sadece giden dalı seçer
  • awk '{print $1}' yalnızca dalların adını görüntülemek için çıktıyı filtreleyin
  • xargs git branch -D tüm çizgiler (dallar) üzerinde döngü yapar ve bu dalı kaldırmaya zorlar

Neden git branch -Ddeğil git branch -dbaşka tam birleştirilmez şubeleri için sahip olacaktır.

error: The branch 'xxx' is not fully merged.

1
usta yerine uzaktan söylemek istedin mi?
tinos

8

Bunu yapabilirsin:

git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d

7

Yukarıdaki bilgilere dayanarak, bu benim için çalıştı:

git br -d `git br -vv | grep ': gone] ' | awk '{print $1}' | xargs`

': gone] 'Uzaktan olan tüm yerel şubeleri kaldırır .


1
Görünüşe göre bu, son işlem mesajında ​​"gitmiş" tüm şubeleri de kaldıracaktır.
dlsso

Ayrıca goneadının herhangi bir yerinde olan tüm dalları da kaldıracaktır .
bfontaine

3
"git branch -D git branch -vv | grep ': gone]' | awk '{print $ 1}' | xargs`" Bu benim için işe yaradı.
Muthu Ganapathy Nathan

7
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d

Yukarıdaki komut, uzaktan birleştirilen ve silinen şubeleri getirmek için kullanılabilir ve artık uzaktan kumandada bulunmayan yerel şubeyi siler


Şimdiye kadarki en iyi çözüm, grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -Dhepsini silmeye zorlamak için değiştirdim
Shoaib

Şube adlarınızdan herhangi biri alt dizeyi içinde goneherhangi bir yerde içeriyorsa tehlikelidir (örneğin usingonefunction).
Toby Speight

7

Bunların hiçbiri benim için gerçekten doğru değildi. originUzak dalı silinen ( gone) uzak bir dalı izleyen tüm yerel dalları temizleyecek bir şey istedim . Hiçbir zaman uzak bir dalı izlemek için ayarlanmamış yerel şubeleri silmek istemedim (yani: yerel geliştirici şubelerim). Ayrıca git, özel komut dosyaları yazmak yerine, sadece kullanan basit bir astar veya diğer basit CLI araçlarını istedim . Biraz kullanarak grepve awkbu basit komutu yapmak için sona erdi .

Sonuçta bu benim sonuçlandı ~/.gitconfig:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

İşte git config --global ...bunu kolayca eklemek için bir komut git prune-branches:

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'

NOT: config komutunda, gerçek yapılandırmamda yaptığım gibi değil , -dseçeneğini kullanıyorum . Ben kullanıyorum çünkü Git'in birleştirilmemiş dallardan şikayetçi olduğunu duymak istemiyorum. Bu işlevi de isteyebilirsiniz. Öyleyse , bu config komutunun sonunda yerine kullanın.git branch-D-D-D-d


Git takma adı yaklaşımını seviyorum. Hızlı soru: Neden yaptığını git branch -vvve için greping : gone]ve yapmaması git branch -viçin ve grep [gone]?
Lalbi

@ lalibi, güzel soru. Hatırlamıyorum. Bir şeyin sadece biriyle görünmediğinden şüpheleniyorum v. Eğer git branch -v | grep '[gone]'sizin için işler, ne duruyorsunuz. Biraz daha temiz görünüyor.
Karl Wilbur

4

Dayanarak Silme Eski Yerel Şube: Git İpucu , benzer jason.rickman çözümüyle aradım bu amaç için özel bir komut uygulanan git gitmiş Bash kullanarak:

$ git gone
usage: git gone [-pndD] [<branch>=origin]
OPTIONS
  -p  prune remote branch
  -n  dry run: list the gone branches
  -d  delete the gone branches
  -D  delete the gone branches forcefully

EXAMPLES
git gone -pn    prune and dry run
git gone -d     delete the gone branches

git gone -pn budama ve "gitti" dalları listeleme birleştirir:

$ git gone -pn
  bport/fix-server-broadcast         b472d5d2b [origin/bport/fix-server-broadcast: gone] Bump modules
  fport/rangepos                     45c857d15 [origin/fport/rangepos: gone] Bump modules

Ardından git gone -dveya tuşunu kullanarak tetiği çekebilirsiniz git gone -D.

notlar

  • Kullandığım normal ifade normalde "$BRANCH/.*: gone]"nerede $BRANCHolacağıdır origin. Git çıkışınız Fransızca vb. Olarak yerelleştirilmişse, bu muhtemelen işe yaramaz.
  • Sebastian Wiesner ayrıca Windows kullanıcıları için Rust'a taşıdı. Buna gitmiş de denir .

Bu muhtemelen kabul edilen cevap olmalıdır - OP'nin sorununu çözen git gonebir takma ad gibi görünüyor git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d.
alex

4

Bir ağırca Çizim sayısının ait diğer cevaplar burada herhangi bir çalışması gerekir ki, ben aşağıdaki ile sona erdi ettik (git 2.13 ve üzeri sadece inanıyorum) UNIX benzeri kabuk:

git for-each-ref --shell --format='ref=%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)' refs/heads | while read entry; do eval "$entry"; [ ! -z "$ref" ] && git update-ref -d "$ref" && echo "deleted $ref"; done

Bu özellikle for-each-refyerine kullanılır branch( branchmakine tarafından değil, insan tarafından okunabilen çıktı için tasarlanmış bir "porselen" komutu gibi) ve --shellargümanını düzgün bir şekilde kaçan çıktı almak için kullanır (bu, ref adındaki herhangi bir karakter için endişelenmemizi sağlar).


Benim için işe yarıyor, ancak komuttaki diğer adımların ne yaptığını açıklayabilirseniz de iyi olurdu. Mesela ne [ ! -z "$ref" ]demek bilmiyorum . Bence bir çok astar zaten yardımcı olurdu. Ama yine de girişiniz için teşekkürler!
KevinH

4

Yine başka bir cevap, çünkü çözümlerin hiçbiri zarafet ve platformlar arası olma ihtiyacımı karşılamıyor:

Uzakta olmayan yerel dalları silme komutu:

for b in $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads); do git branch -d $b; done

Gitconfig ile entegre etmek için aşağıdakilerle çalıştırılabilir git branch-prune:

darbe

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format='\''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'\'' refs/heads); do git branch -d $b; done'

Güç kalkanı

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format=''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'' refs/heads); do git branch -d $b; done'

(PowerShell ve bash için evrensel bir komut bulma konusunda yardıma ihtiyacınız var)

Bu cevap neden en iyisidir?

  • Eksiksiz bir çözüm sunar: git'inize bir git branch-prunekomut ekler
  • Windows PowerShell'den sorunsuz çalışır
  • Temelindeki düşünce, jason.rickman @ s' kurşun yöntemi kullanılarakgit for-each-ref
  • Ayrıştırma ve filtreleme --filterharici bağımlılık gerektirmeden yapılır

Açıklama:

  • Cihazınıza yeni bir takma ad ekler ~\.gitconfig. Bunu yaptıktan sonragit branch-prune
  • Bu takma adın içinde:
    • --prune"Uzaktan izleme dallarını artık uzaktan kumandada olmayan kuru erik" bayrağını içeren dalları getirir.
    • Kullanır git for-each-refve --filterdalların bir listesini almak için [gone](uzaktan kumanda yok)
    • Bu listede dolaşır ve şubeyi güvenli bir şekilde siler

1
@ Jerry-wu , bu çözümün mükemmelliğini sonsuza kadar geliştirdiğiniz için teşekkür ederiz .
Himura

@ jerry-wu ve git config komutunun son düzenlemesi PowerShell'de çalışmıyor ((
Himura

1

Bu bash senaryosunu buldum. Her zaman dalları tutmak develop, qa, master.

git-clear() {
  git pull -a > /dev/null

  local branches=$(git branch --merged | grep -v 'develop' | grep -v 'master' | grep -v 'qa' | sed 's/^\s*//')
  branches=(${branches//;/ })

  if [ -z $branches ]; then
    echo 'No branches to delete...'
    return;
  fi

  echo $branches

  echo 'Do you want to delete these merged branches? (y/n)'
  read yn
  case $yn in
      [^Yy]* ) return;;
  esac

  echo 'Deleting...'

  git remote prune origin
  echo $branches | xargs git branch -d
  git branch -vv
}

1

Hile yapmak için kısa bir yöntem kullanıyorum, birkaç saatten tasarruf edebileceğiniz ve size daha fazla görünürlük kazandırabileceğiniz şekilde yapmanızı öneririz.

Aşağıdaki snippet'i .bashrc'nize (macos'ta .bashprofile) ekleyin.

git-cleaner() { git fetch --all --prune && git branch --merged | grep -v -E "\bmaster|preprod|dmz\b" | xargs -n 1 git branch -d ;};
  1. Tüm uzaktan kumandaları getir
  2. Git'ten yalnızca birleştirilmiş şubeler alın
  3. Bu listeden "korumalı / önemli" dalları kaldırın
  4. Kalanı çıkarın (örneğin, temiz ve birleştirilmiş dallar)

Gereksinimlerinize uyacak şekilde grep normal ifadesini düzenlemeniz gerekir (burada master, preprod ve dmz'nin silinmesini önler)


git fetch --all --prunehile yaptı. Teşekkürler!
LeOn - Han Li

1

Bu benim için çalıştı:

git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

oh, ben bu yazı çift yayınlanmıştır ... sadece mesajları incelerken gördüm. Ama bunu sizinki olarak almak yerine bu komutu sağlayan adama gerçekten işaret edebilirsiniz!
Dwza

Bir forumdan alıyorum akıllı olmaya çalışmayın sadece cevap almak ya da görmezden gelmek
Fareed Alnamrouti

Yapabileceğinden bile ... neyse ... buraya seninle konuşmak için gelmedim.
Dediğin

0

Ne kadar süreceğinden emin değilim, ama şimdi git-up kullanıyorum, bu da bununla ilgileniyor.

Yaparım git upve yeni dalları izlemeye başlar ve eskilerini siler.

Açıkça söylemek gerekirse, kullanıma hazır git komutu değil - https://github.com/aanand/git-up

BTW aynı zamanda kirli ağacı saklar ve hala ile taban yapar git up.

Umarım birisi için faydalı olur


2
Bu, sunucuda bulunmayan yerel şubeleri silmez.
Ashley

0

İşte balık kabuğu için kullandığım bir çözüm. Üzerinde test Mac OS X 10.11.5, fish 2.3.0ve git 2.8.3.

function git_clean_branches
  set base_branch develop

  # work from our base branch
  git checkout $base_branch

  # remove local tracking branches where the remote branch is gone
  git fetch -p

  # find all local branches that have been merged into the base branch
  # and delete any without a corresponding remote branch
  set local
  for f in (git branch --merged $base_branch | grep -v "\(master\|$base_branch\|\*\)" | awk '/\s*\w*\s*/ {print $1}')
    set local $local $f
  end

  set remote
  for f in (git branch -r | xargs basename)
    set remote $remote $f
  end

  for f in $local
    echo $remote | grep --quiet "\s$f\s"
    if [ $status -gt 0 ]
      git branch -d $f
    end
  end
end

Birkaç not:

Doğru ayarı yaptığınızdan emin olun base_branch. Bu durumda developtaban dalı olarak kullanıyorum , ama her şey olabilir.

Bu kısım çok önemli: grep -v "\(master\|$base_branch\|\*\)". Master'ı veya ana dalınızı silmemenizi sağlar.

Kullandığım git branch -d <branch>bu yüzden tamamen düzeltilmiş yukarı veya geçerli BAŞ ile birleşti henüz herhangi dalı silemezsiniz olarak, ekstra bir önlem olarak.

Test için kolay bir yol değiştirmektir git branch -d $file echo "will delete $f".

Ayrıca eklemeliyim: KENDİ RİSKİNİZDE KULLANIN!


0

Uzakta olmayan yerel dalları silmek için GitPython kullanarak bir Python komut dosyası yazdım .

    import git
    import subprocess
    from git.exc import GitCommandError
    import os

    def delete_merged_branches():
        current_dir = input("Enter repository directory:")
        repo = git.Repo(current_dir)
        git_command = git.Git(current_dir)

        # fetch the remote with prune, this will delete the remote references in local.
        for remote in repo.remotes:
            remote.fetch(prune=True)

        local_branches = [branch.name for branch in repo.branches]
        deleted_branches = []

        # deleted_branches are the branches which are deleted on remote but exists on local.
        for branch in local_branches:
            try:
                remote_name = 'origin/'+ branch
                repo.git.checkout(remote_name)
            except GitCommandError:
            # if the remote reference is not present, it means the branch is deleted on remote.
                deleted_branches.append(branch)

        for branch in deleted_branches:
            print("Deleting branch:"+branch)
            git_command.execute(["git", "branch", "-D",branch])


        # clean up the work flow.
        repo.git.checkout('master')
        repo.git.pull()

    if __name__ == '__main__':
        delete_merged_branches()

Umarım birisi faydalı bulur, lütfen bir şey kaçırırsam yorum ekleyin.


0

Kurulmuş bir zshkabuk kullanıyorsanız Oh My Zsh, bunu güvenli bir şekilde yapmanın en kolay yolu yerleşik otomatik tamamlamayı kullanmaktır.

İlk olarak hangi şubeleri silmek istediğinizi belirleyin:

~ git branch --merged

  branch1
  branch2
  branch3
* master

bu size zaten birleştirilmiş şubelerin bir listesini gösterir

Silmek istediğiniz birkaç tanesini bildikten sonra şunu yazın:

~ git branch -d 

Tek yapmanız gereken [sekme] tuşuna bastığınızda size yerel şubelerin bir listesini gösterecektir. Sekme tamamlandı seçeneğini kullanın veya tekrar [sekme] tuşuna basın; [enter] tuşuyla bir şube seçmek için bu sekmeler arasında geçiş yapabilirsiniz.

Sekme Silmek istediğiniz dalların bir listesine sahip olana kadar dalları tekrar tekrar seçin:

~ git branch -d branch1 branch2 branch3

Şube koleksiyonunuzu silmek için enter tuşuna basmanız yeterli.

Terminalinizde zsh kullanmıyorsanız ... Buradan alın.


0

Boruları kullanmayı seviyorum çünkü komutu okumayı kolaylaştırıyor.

Master hariç tüm dalları kaldırmak istiyorsanız bu benim çözümüm.

git branch | grep -v master | xargs -n 1 git branch -D

Ölçütlerinize uyan diğer dalları silmek için birinci ve ikinci bloğu değiştirin.

git branch --merged | grep feature_name | xargs -n 1 git branch -D

-3

Bir git istemcisi kullanarak benim için çalışan basit cevap:

Depoyu makinenizden tamamen silin ve tekrar kontrol edin.

Riskli senaryolarla uğraşmak yok.


2
Şu anda üzerinde çalıştığım dallar ne olacak: /
Mailo Světel

@ MailoSvětel uzaktan kumandanızdalarsa, onları tekrar çekebilirsiniz (en son çalışmanızı uzaktan kumandanıza aktarmayı unutmayın!)
Juan Carlos Ospina Gonzalez

Sorumda ve cevapların çoğunda gereksiz çalışmalardan kaçınmaya çalışıyoruz. Başka bir deyişle: Yapmam gereken sadece dalları kaldırmak, artık üzerinde çalışmayacağım. Repoyu kaldırmak, klonlamak ve şubeleri tekrar izlemeye başlamak benim için gereksiz bir iş. Bunun yanı sıra, bazı işler kaybolabilir :(
Mailo Světel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.