Tüm yerel git dallarını sil


323

Her yeni özellik veya hikaye kartı için yeni bir yerel şube oluşturduğum bir geliştirme sürecini takip ediyorum. İşiniz bittiğinde dalı master'a birleştiriyorum ve sonra itiyorum.

Tembellik veya unutkanlığın bir kombinasyonu nedeniyle zamanla gerçekleşme eğilimi, bir kısmı (sivri uçlar gibi) birleştirilmemiş olabilecek geniş bir yerel şubeler listesi ile sonuçlanmam.

Tüm yerel şubelerimi listelemeyi biliyorum ve tek bir şubeyi nasıl kaldıracağımı biliyorum, ancak tüm yerel şubelerimi silmeme izin veren bir git komutu olup olmadığını merak ediyordum?

git branch --mergedKomutun çıktısı aşağıdadır .

user@machine:~/projects/application[master]$ git branch --merged
  STORY-123-Short-Description
  STORY-456-Another-Description
  STORY-789-Blah-Blah
* master

Listelenen şubeleri grep -v \*(aşağıdaki yanıtlara göre) silmeye yönelik tüm girişimler hatalarla sonuçlanır:

error: branch 'STORY-123-Short-Description' not found.
error: branch 'STORY-456-Another-Description' not found.
error: branch 'STORY-789-Blah-Blah' not found.

Ben kullanıyorum:
git 1.7.4.1
ubuntu 10.04
GNU bash, sürüm 4.1.5 (1) -rease
GNU grep 2.5.4


7
@Andrew'un cevabını kabul etmenizi istiyorum!
Robert Siemer


@GiulioCaccin Soru aynı zamanda birleştirilmemiş dallarla da ilgilidir ve soruyu açıkça yansıtmak için güncelledim.
Louth

Yanıtlar:


384

'Git branch -d' alt komutu birden fazla dalı silebilir. Yani, @ sblom'un cevabını basitleştirmek ama kritik bir xargs eklemek:

git branch -D `git branch --merged | grep -v \* | xargs`

veya aşağıdakilerle daha da basitleştirilmiştir:

git branch --merged | grep -v \* | xargs git branch -D 

Önemli olarak, @AndrewC tarafından belirtildiği gibi, git branchkomut dosyası kullanmak için kullanılması önerilmez. Bundan kaçınmak için aşağıdaki gibi bir şey kullanın:

git for-each-ref --format '%(refname:short)' refs/heads | grep -v master | xargs git branch -D

Dikkat silme konusunda garantilidir!

$ mkdir br
$ cd br; git init
Initialized empty Git repository in /Users/ebg/test/br/.git/
$ touch README; git add README; git commit -m 'First commit'
[master (root-commit) 1d738b5] First commit
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README
$ git branch Story-123-a
$ git branch Story-123-b
$ git branch Story-123-c
$ git branch --merged
  Story-123-a
  Story-123-b
  Story-123-c
* master
$ git branch --merged | grep -v \* | xargs
Story-123-a Story-123-b Story-123-c
$ git branch --merged | grep -v \* | xargs git branch -D
Deleted branch Story-123-a (was 1d738b5).
Deleted branch Story-123-b (was 1d738b5).
Deleted branch Story-123-c (was 1d738b5).

Bu komut yine de aşağıdaki cevabın yorumlarında belirtilenlerle aynı hataları rapor eder. error:branch 'STORY-123-Short-Description' not found.listelenen her şube için.
Louth

1
Benim için çalışıyor; ayrıntılar eklenmiş olarak yukarıya bakın.
GoZoner

1
Peki, git 1.7.10 sorununuzu çözdü mü yoksa doğrudan .git deposunda çalışmayı mı tercih ediyorsunuz?
GoZoner

1
Bir error:branch 'STORY-123-Short-Description' not found.hata alırsanız , bu muhtemelen git renk ayarlarından kaynaklanmaktadır. Bu benim için çalıştı ( --no-colorseçeneği not ):git branch --no-color --merged | grep -v \* | xargs git branch -D
marcok

3
SO üzerinde tek cevap işe yaradığını buldum. Teşekkür ederim!
Kevin Suttle

140

Ben github bu konuda bir yorumda daha güzel bir yol buldum :

git branch --merged master --no-color | grep -v master | grep -v stable | xargs git branch -d

edit: renksiz seçenek eklendi ve sabit dal hariç (davanızdaki diğer dalları ekleyin)


2
Sonunda, ihtiyacım olan çözüm
Code Whisperer

1
Bunu denedim ama error: branch 'my-branch-name' not found.her dal için almaya devam ettim . Git 1.8.3.4 sürümünü (Apple Git-47) kullanma. Neden olduğu hakkında bir fikrin var mı?
wheresrhys

deneyin 'git branch - birleştirilmiş master | grep -v ustası | xargs echo 'neyi tam olarak silmeye çalıştığını ayıklamak için? daha iyi bir fikrim yok ...
mBardos

2
Yani. git for-each-ref --format '%(refname:short)' refs/heads/ | grep -v master | xargs git branch -d
Павел Тявин

1
Bununla birlikte xargs kullanımını öğrendim. Teşekkürler
Volem

105

Çıktısının ayrıştırılması git branchönerilmez ve Yığın Taşması konusunda gelecekteki okuyucular için iyi bir yanıt değildir.

  1. git branchporselen komutanlığı olarak bilinen şeydir. Porselen komutları makine tarafından ayrıştırılmak üzere tasarlanmamıştır ve çıktı Git'in farklı sürümleri arasında değişebilir.
  2. git branchÇıktısını ayrıştırmayı zorlaştıracak şekilde değiştiren kullanıcı yapılandırma seçenekleri vardır (örneğin, renklendirme). Bir kullanıcı ayarladıysa color.branch, çıkışta kontrol kodları alırsınız, bu da error: branch 'foo' not found.başka bir komuta borulamaya çalıştığınızda ortaya çıkar. Bunu --no-colorbayrakla geçebilirsiniz git branch, ancak diğer kullanıcı yapılandırmalarının işleri bozabileceğini kim bilebilir?
  3. git branch Ayrıştırmak için can sıkıcı başka şeyler yapabilir, örneğin şu anda teslim alınmış dalın yanına yıldız işareti koymak

Git sürdürme söylemek üzere etrafında komut dosyası hakkında git branchçıkışı

Mevcut dalın ne olduğunu bulmak için, sıradan / dikkatsiz kullanıcılar git dalının etrafında komut dosyası yazmış olabilir, bu da yanlıştır. Git şubesi de dahil olmak üzere herhangi bir Porselen komutunun komut dosyalarında kullanılmasına karşı aktif olarak cesaret kırıyoruz, çünkü komuttan elde edilen çıktı, insan tüketimini kullanma durumuna yardımcı olmak için değişebilir.

.gitDizindeki dosyaları manuel olarak düzenlemeyi öneren yanıtlar (.git / refs / heads gibi) benzer şekilde sorunludur (bunun yerine referanslar .git / packed-refs içinde olabilir veya Git gelecekte iç düzenlerini değiştirebilir).

Git, for-each-refdallar listesini alma komutunu sağlar .

Git 2.7.X, --mergedbirleştirilmiş tüm dalları bulmak ve silmek için aşağıdaki gibi bir şey yapabilmeniz için seçeneği tanıtacaktır.HEAD

for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
do
    git branch -d ${mergedBranch}
done

Git 2.6.X ve daha eski sürümlerde, tüm yerel şubeleri listelemeniz ve daha sonra birleştirilip birleştirilmediklerini görmek için ayrı ayrı test etmeniz gerekir (bu, önemli ölçüde daha yavaş ve biraz daha karmaşık olacaktır).

for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
do
    git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
done

git branch --no-color 2>/dev/null?
nobar

5
Kesinlikle bir gelişme. Her zaman * 'yi filtrelemeye ihtiyaç duyma probleminiz olacaktır ve birisi onu müstakil kafasından çalıştırırsa eğlenceli şeyler yapar. Ana sorun git branchporselen komutudur ve git'in gelecekteki bazı versiyonlarında çıkışın değişmeyeceğine dair bir garanti yoktur.
Andrew C

@AndrewC - Bu hem gizemli "şube bulunamadı" hataları ile ilgili soruya cevap ve daha uygun bir komut kullanarak çalışan bir çözüm sağlar! 👍
Jason

2
'Porselen' ve 'Porselen olmayan' GIT komutları nasıl tanımlanır?
GoZoner

1
Muhtemelen varsayılan olarak 'dev' ve 'master'ı hariç tutmak için yararlı bir iyileştirme olur mu?
PandaWood

66

Tüm dalları silmenin ancak "geliştirme" ve "ana" gibi diğerlerini korumanın daha basit yolu şudur:

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

çok kullanışlı !


8
Eski bir iş parçacığına dirildiniz ve mevcut olana neredeyse aynı bir cevap gönderdiniz, bu adamcağız ve sahip olduğu güvenlik değişikliklerini kaçırdınız. Bu iyi bir cevap değil.
Andrew C

6
Bu cevap git dalından çıkan boru çıkışında, modifikasyonda ve git dalında -D'ye geçmede açıktır. Kaba olmaya gerek yok.
Pam

Bu çözüm benim için çalıştı. Tüm yerel şubeler silindi.
Prad

1
Bu, 'develop_feature' veya 'master_feature' gibi word develop veya master içeren hiçbir dalı silmez.
django

BU 👆🏻 ARIYORUM CEVAP
Konrad G

62

Şu anda teslim aldığınız şube hariç her dalı silmek için:

for b in `git branch --merged | grep -v \*`; do git branch -D $b; done

Ben değiştirmeyi öneriyoruz git branch -D $bbir etmek echo $bbu hesabın düşündüklerini dalları siler emin olmak için ilk birkaç kez.


1
Bu komutla error:branch 'a_branch_name' not found.ne yapmaya çalıştığınızı görebiliyorum ve komutla oynuyorum ama nedense git verilen şube isimlerini beğenmiyor ...
Louth

hmmm. sorun gidermeye yardımcı olmak için,git branch --merged
sblom'dan

benim şube isimlerimSTORY-123-Short-Description
Louth

ve koştuğunuzda git branch --merged, her satırdakilerden biriyle bir liste alırsınız?
sblom

1
tam anlamıyla diyor error:branch 'a_branch_name' not found.mu? Veya git branchyukarıdaki çıktınızdaki şube adlarından biri hakkında şikayetçi mi?
sblom

52

Aşağıdaki komut, ana şube dışındaki tüm yerel dalları siler.

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

Yukarıdaki komut

  1. tüm şubeleri listele
  2. Listeden ana dalı yok sayın ve geri kalan dalları alın
  3. şubeyi sil

4
git branch | grep -v "master" | xargs git branch -dİlk önce kullanacağım, bu yüzden birleştirilmemiş dalları silmiyorum, sadece güvende olmak için. Ama güzel cevap!
Jonas Lomholdt

3
İşte bir powershell versiyonu,@(git branch | Select-String -Pattern "[^(*?)\s? master]") | ForEach-Object{$_.Line.Trim()} | %{git branch -D $_}
Jonas Lomholdt

1
@baklazan Bu, yalnızca bazı araçlar yüklüyse Windows 10 komut satırında çalışır. Muhtemelen MINGW veya başka bir şey var ve bunu bilmiyorsun.
KthProg

42

Sadece bir not, git 1.7.10'a yükseltirim. Burada, sürümünüzde çalışmayan yanıtlar alıyor olabilirsiniz. Benim tahminim, şube isminin önüne ön ek eklemeniz gerekecek refs/heads/.

DİKKAT, yalnızca çalışma klasörünüzün ve .git dizininizin bir kopyasını yaptıysanız aşağıdakilere devam edin.

Bazen devam edip doğrudan istemediğim dalları siliyorum .git/refs/heads. Tüm bu dallar, işaret ettikleri taahhüdün 40 karakter sha-1'ini içeren metin dosyalarıdır. .git/configBunlardan herhangi biri için özel bir izleme ayarladıysanız, size fazladan bilgi verilecektir . Bu girişleri manuel olarak da silebilirsiniz.


Sonunda basit ve pragmatik bir seçenek.
Sevdim

2
Paketlenmiş referanslarınız varsa veya bazen uzak bir sunucudan klonlansanız bile (bu size paketlenmiş dosyalar sağlayacaktır) çalışmaz. Eğer başvurularınız paketlenmişse, referanslar .git / refs / heads dosyasında saklanmaz, "paket başvuruları" adlı bir dosyada saklanır. Bkz. Git-scm.com/docs/git-pack-refs .
Alexander Bird

1
Şu anda kontrol ettiğiniz şubeyi kaldırmak kötü bir fikir gibi görünüyor
Moberg

@Moberg Önceden bir taahhütte bulunun ve müstakil HEAD iyi durumda olacaktır.
RomainValeri

34

Aşağıdaki kabuk komutunu deneyin:

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

Açıklama:

  • Command Tüm şubeleri git branch | grep -v "master"komutla al
  • Her şube seçiniz 👇 xargskomutu
  • 💦 Şube ile sil xargs git branch -D

3
Her ne kadar bu doğru bir cevap olabilir. Orijinal soruyu neyin ve nasıl çözdüğünün açıklaması olmadan bir kod satırı çok kullanışlı değildir. Lütfen cevabınıza ayrıntıları veriniz.
RyanNerd

28

Bulunduğunuz yer dışındaki linux'daki tüm yerel şubeleri silmek için

// hard delete

git branch -D $(git branch)

2
Bu, .git'e girmek ve bir şeyleri kaldırmaktan daha güvenli hissediyor.
nelsontruran

25

Sadece metin düzenleyici ve kabuk kullanmayı daha kolay buldum.

  1. Tip git checkout <TAB>kabukta. Tüm yerel şubeleri gösterecek.
  2. Bunları bir metin düzenleyicisine kopyalayın, saklamanız gerekenleri kaldırın.
  3. Satır sonlarını boşluklarla değiştirin. (SublimeText'te çok kolay.)
  4. Açık kabuk, yazın git branch -D <PASTE THE BRANCHES NAMES HERE>.

Bu kadar.


Üzerinde durduğunuz dalı çıkarabileceğinizi sanmıyorum.
Dong Thang

@Dong Bu dalın yanında bir * var, bu yüzden kopyalanan listeden kaldırmanız yeterli!
Melanie

12

Benzer bir durum yaşadım ve son zamanlarda aşağıdaki komutu yararlı buldum.

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep>/) printf "%s", $0 }'`

Birden fazla dalı tutmak istiyorsanız,

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep1>|<Branch_You_Want_to_Keep2>/) printf "%s", $0 }'`

umarım bu birisine yardım eder.


1
Güzel bir ama işe almak için backticks gerekiyordu.Aslında git branch -D `git branch | awk '{ if ($0 !~ /master/) printf "%s", $0 }'` onları aslında var mı ama SO biçimlendirme kayboldu düşünüyorum.
tassinari

10

Windows Komut Satırı'ndan, şu anda kullanıma alınmış dal dışında tümünü silin:

for /f "tokens=*" %f in ('git branch ^| find /v "*"') do git branch -D %f

7

Git'in kendisinden geçmeniz gerekmiyorsa, .git / refs / heads altındaki kafaları manuel veya programlı olarak da silebilirsiniz . Aşağıdakiler Bash altında minimum ayarlamayla çalışmalıdır:

shopt -s extglob
rm -rf .git/refs/heads/!(master)

Bu, ana dalınız dışındaki her yerel dalı silecektir. Memba şubeleriniz .git / refs / remotes altında depolandığından , dokunulmadan kalacaktır.

Bash kullanmıyorsanız veya aynı anda çok sayıda Git deposunu geri almak istiyorsanız, GNU find ile benzer bir şey yapabilirsiniz:

find . \
    -path remotes -path logs -prune -o \
    -wholename \*.git/refs/heads/\* \! -name master -print0 |
xargs -0 rm -rf

Bulma çözümü muhtemelen daha taşınabilirdir, ancak budama yolları ve dosya adları zor ve potansiyel olarak daha fazla hataya açıktır.


Güzel. Görsel silme :)
sandalone

5

Cevapların hiçbiri ihtiyaçlarımı tam olarak karşılamadı, bu yüzden başlıyoruz:

git branch --merged | grep -E "(feature|bugfix|hotfix)/" | xargs git branch -D && git remote prune origin

Bu Birleştirilip ile başlayan tüm yerel şubeleri silecektir feature/, bugfix/ya hotfix/. Daha sonra yukarı yönlü uzaktan kumandaorigin budanır (bir parola girmeniz gerekebilir).

Git 1.9.5 üzerinde çalışır.


5

Burada bir dizi cevabın kombinasyonuna dayanarak - uzaktaki tüm dalları tutmak, ancak geri kalanını silmek istiyorsanız , aşağıdaki oneliner hile yapacaktır:

git for-each-ref --format '%(refname:short)' refs/heads | grep -Ev `git ls-remote --quiet --heads origin | awk '{print substr($2, 12)}'| paste -sd "|" -` | xargs git branch -D

3

Bu bir komut satırı çözümü olmasa da, Git GUI'nin henüz önerilmediğine şaşırdım .

Komut satırını zamanın% 99'unu kullanıyorum, ancak bu durumda ya yavaşlamak için çok uzak (bu nedenle orijinal soru) ya da uzun, ama akıllı bir kabuk manipülasyonuna başvururken ne silmek istediğinizi bilmiyorsunuz.

Kullanıcı arabirimi bu sorunu çözer, çünkü her bir dal için bir komut yazmak zorunda kalmadan kaldırılmasını istediğiniz dalları hızlı bir şekilde kontrol edebilir ve saklamak istediğiniz dalları hatırlatabilirsiniz.

Kullanıcı arayüzünden Şube -> Sil ve Ctrl + seçeneğine giderek silmek istediğiniz dalları vurgulayın. Eğer olmak istiyorsan, bunların bir dal (örneğin birleştirilir devaltında) Birleştirilmiş içine Sadece eğer Sil set Yerel Şube için dev. Aksi takdirde, bu kontrolü yok saymak için Her zaman olarak ayarlayın .

GitUI: yerel şubeleri sil


1

Powershell için bu işe yarar:

git branch --format '%(refname:lstrip=2)' --merged `
    | Where-Object { $_ -ne 'master' } `
    | ForEach-Object { git branch -d $_ }

0

Aşağıdaki komut dosyası dalları siler. Kullanın ve kendi sorumluluğunuzdadır, vb.

Bu sorudaki diğer cevaplara dayanarak, kendim için hızlı bir bash senaryosu yazdım. Ben "gitbd" (git branch -D) olarak adlandırdım ama eğer kullanırsanız, istediğiniz gibi yeniden adlandırabilirsiniz.

gitbd() {
if [ $# -le 1 ]
  then
    local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
    printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
    read -n 1 -r # Immediately continue after getting 1 keypress
    echo # Move to a new line
    if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
      then
        echo $branches_to_delete | xargs git branch -D
    fi
else
  echo "This command takes one arg (match pattern) or no args (match all)"
fi
}

Bir desen bağımsız değişkeni ile eşleşiyorsa, geçirilen tüm dalları veya bağımsız değişkenlerle çağrıldığında tüm yerel dalları silmeyi önerecektir. Aynı zamanda size bir onay adımı da verecektir, çünkü biliyorsunuz, bir şeyleri siliyoruz, bu güzel.

Bu biraz aptal - desenle eşleşen dal yoksa, bunu fark etmez.

Örnek bir çıkış çalışması:

$ gitbd test
Matching branches:

dummy+test1
dummy+test2
dummy+test3

Delete? [Y/n] 

0

Ben hariç tüm yerel şubeleri kaldırmak için bir kabuk komut dosyası yazdım develop

branches=$(git branch | tr -d " *")
output=""
for branch in $branches 
do
  if [[ $branch != "develop" ]]; then
    output="$output $branch"
  fi
done
git branch -d $output

0

Yukarıdaki cevaplar iyi çalışıyor. İşte yerel repoda çok sayıda şubemiz olduğunda ve yerel makinede yatan az sayıda dal hariç birçok şubeyi silmemiz gerektiğinde başka bir yaklaşım.

İlk git branchönce tüm yerel şubeleri listeleyecektir.

Bir unix komutu çalıştırarak şube adlarının sütununu dosyadaki tek bir satıra aktarmak için
git branch > sample.txt
Bu, sample.txt dosyasına kaydedilecektir. Ve koş
awk 'BEGIN { ORS = " " } { print }' sample.txt
komutu kabukta . Bu, sütunu satıra dönüştürür ve şube adları listesini tek bir satıra kopyalar.

Ve sonra koş
git branch -D branch_name(s).
Bu işlem yerel olarak listelenen tüm şubeleri silecektir


0

En pragmatik yol: Üzerinde mastertaahhüt edilmemiş çalışmanız olmadığından emin olun , gerekiyorsa taahhüt edin / itin, deponun yeni bir kopyasını kopyalayın ve eskisini silin.


0

Bu amaçla git-extras'ı kullanabilirsiniz

$ git delete-merged-branches
Deleted feature/themes (was c029ab3).
Deleted feature/live_preview (was a81b002).
Deleted feature/dashboard (was 923befa).

0

Kutumda grep veya diğer unix yok ama bu VSCode terminalinden çalıştı:

git branch -d $(git branch).trim()

Birleştirilmemiş dalları silmemesi için küçük d harfini kullanıyorum.

Bunu yaparken de ustaydım, bu yüzden * masteryok , bu yüzden ustayı silmeye çalışmadı.


Onaylandı: Açık değilse master, bu komut SİLECEKTİR master.
Brett Rowberry

-1

Önce bunu yaptığınızdan emin olun

git fetch

Tüm uzak şube bilgilerine sahip olduğunuzda, master hariç her bir dalı kaldırmak için aşağıdaki komutu kullanın

 git branch -a | grep -v "master" | grep remotes | sed 's/remotes\/origin\///g' | xargs git push origin --delete
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.