Eski uzak git dalları Temizleme


696

İki farklı bilgisayardan (A ve B) çalışıyorum ve dropbox dizininde ortak bir git uzaktan kumandasını saklıyorum.

Diyelim ki iki şubem var, efendi ve devel. Her ikisi de uzak muadillerini orijin / master ve orijin / devel izliyor.

A bilgisayarındayken, yerel ve uzaktaki dal devel'i siliyorum.

git push origin :heads/devel
git branch -d devel

Koşu git branch -aA bilgisayarında, ben şube aşağıdaki listeyi olsun.

  • usta
  • köken / BAŞ
  • köken / ana

Koşu git fetchB bilgisayarında, ben yerel devel şube kaldırabilir git branch -d develama uzak devel şube kaldıramazsınız.

git push origin :heads/devel aşağıdaki hata iletilerini döndürür.

hata: kalifiye olmayan hedefe itilemiyor: heads / proxy3d
Hedef refspec, ne uzaktan kumandadaki mevcut bir ref ile eşleşmiyor ne de refs / ile başlıyor ve kaynak ref'ye dayalı bir önek tahmin edemiyoruz.
ölümcül: Uzak uç beklenmedik bir şekilde telefonu kapattı

git branch -a hala uzak dallarda orijin / devel listeleniyor.

Uzak dalları B bilgisayarından nasıl temizleyebilirim?


4
Bunu deneyen biri tarafından, Dropbox klasörlerindeki git depolarının biraz kırılgan olduğu (ancak ek ayrıntılar olmadan) söylendi.
Thorbjørn Ravn Andersen

5
@ ThorbjørnRavnAndersen muhtemelen diğer makinede kullanmanın güvenli olduğundan emin olmadan önce (ve o zaman bile başka bir senkronizasyon gerekir) emin olun.
ataulm

Yanıtlar:


1240

İlk olarak, git branch -aB makinesinin sonucu nedir?

İkincisi, zaten sildiğiniz heads/develüzerinde origino yüzden neden makine B'den silemezsiniz ki

Deneyin

git branch -r -d origin/devel

veya

git remote prune origin

veya

git fetch origin --prune

ve gerçekten çalıştırmadan çalıştırmanın sonucunu görmek için ifadenizin --dry-runsonuna eklemekten çekinmeyin git.

İçin Dokümanlar git remote pruneve git branch.


50
git remote prune originbenim için çalıştı => * [pruned] origin/my-old-branch
Hari Karam Singh

126
git remote prune origin --dry-rungerçekte ne yapmadan silineceğini gösterir.
Wolfram Arnold

31
git fetch origin --prunesilinen dalları kaldırmak için mükemmeldi
Sébastien Barbieri

10
Gitmiş bir uzaktan kumandayı izleyen yerel bir şubeniz varsa, hiçbir şey silinmez. Bunlar için, git branch -vvardından gelir git branch -D branchnameve sonunda budama en iyi yoldur.
Roman Starkov

7
Aşağıdaki seçeneği ayarlayarak budamanın çekme / getirme işleminde otomatik olarak gerçekleşmesini yapılandırabilirsiniz:git config remote.origin.prune true
Patrick James McDougle

101

Çalıştırmayı düşünün:

git fetch --prune

Düzenli olarak her bir repoda, silinmiş bir uzak dalı izleyen yerel dalları kaldırmak (uzak GIT deposunda artık mevcut değildir).

Bu daha da basitleştirilebilir

git config remote.origin.prune true

bu, per-repoherhangi bir geleceği git fetch or git pullotomatik olarak budaması için yapacak bir ayardır .

Bunu kullanıcı için ayarlamak üzere global .gitconfig dosyasını düzenleyebilir ve

[fetch]
    prune = true

Ancak, bunun aşağıdaki komut kullanılarak yapılması önerilir:

git config --global fetch.prune true

veya sisteme uygulamak için (sadece kullanıcı için değil)

git config --system fetch.prune true

14

İşte sizin için yapabileceğiniz bash betiği. Http://snippets.freerobby.com/post/491644841/remove-merged-branches-in-git betiğinin değiştirilmiş sürümüdür . Değişikliklerim, farklı uzak konumları desteklemesini sağlıyor.

#!/bin/bash

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 -e "Fetching merged branches...\n"

git remote update --prune
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
    remotes=`echo "$remote_branches" | sed 's/\(.*\)\/\(.*\)/\1/g' | sort -u`
# Remove remote branches
for remote in $remotes
do
        branches=`echo "$remote_branches" | grep "$remote/" | sed 's/\(.*\)\/\(.*\)/:\2 /g' | tr -d '\n'`
        git push $remote $branches 
done

# 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

1
Bu "origin / feature / mybranch" adlı bir dalda kırdı, neden olduğundan emin değilim.
Stavros Korokithakis

Sorun iki seds'de. Değiştir sed 's/\(.*\)\/\(.*\)/\1/g'tarafındansed 's/\([^/]*\)\/\(.*\)/\1/g'
Benoît Latinier

14

Bu komut origin, dışındaki tüm uzak ( ) birleştirilmiş dalları "kuru olarak çalıştırır" master. Bunu değiştirebilir veya master'dan sonra ek dallar ekleyebilirsiniz:grep -v for-example-your-branch-here |

git branch -r --merged | 
  grep origin | 
  grep -v '>' | 
  grep -v master | 
  xargs -L1 | 
  awk '{sub(/origin\//,"");print}'| 
  xargs git push origin --delete --dry-run

İyi görünüyorsa --dry-run,. Ayrıca, bunu önce bir çatal üzerinde test etmek isteyebilirsiniz.


Güzel. Benim tweak 1 xargs + awk yerine perl kullanarak: git branch -r --merged | grep kökenli | grep -v '>' | grep -v ustası | perl -lpe '($ önemsiz, $ _) = bölünmüş (/ \ //, $ _, 2)' | xargs git push origin - silme
Andrew

6

Eğer git branch -rgösterileri uzaktan izleme dalların bir sürü ilgilenen olmadığınızı ve aşağıdaki komutu kullanın, yalnızca yerel kaldırmak istiyorum:

git branch -r | grep -Ev 'HEAD|master|develop'  | xargs -r git branch -rd

Daha güvenli bir sürüm yalnızca birleştirilmiş olanları kaldırmak olacaktır:

git branch -r --merged | grep -Ev 'HEAD|master|develop'  | xargs -r git branch -rd

Bu, diğer takım arkadaşlarının özellik dallarına ihtiyaç duymadığınız ancak ilk klonda çok sayıda uzaktan izleme dalının bulunduğu büyük projeler için yararlı olabilir.

Ancak, bu adım tek başına yeterli değildir, çünkü silinen uzaktan izleme dalları bir sonraki aşamaya geri döner git fetch.

Bu uzaktan izleme dallarını getirmeyi durdurmak için .git / config dosyasında getirilecek başvuruları açıkça belirtmeniz gerekir :

[remote "origin"]
  # fetch = +refs/heads/*:refs/remotes/origin/*    ### don't fetch everything
  fetch = +refs/heads/master:refs/remotes/origin/master
  fetch = +refs/heads/develop:refs/remotes/origin/develop
  fetch = +refs/heads/release/*:refs/remotes/origin/release/*

Yukarıdaki örnekte biz sadece getir master, developve serbest dalları, istediğiniz kadar uygulamaktan çekinmeyin.


1
Teşekkürler, ilk komut benim için çalıştı. Ayrıca yalnızca geçerli dalı (kişisel favorim) almak git fetch origin branchnamegibi bir dal da alabilir veya bir takma ad oluşturabilirsiniz ft = "!f() { git fetch origin $(git rev-parse --abbrev-ref HEAD);}; f". Şerefe.
GiovanyMoreno

Belki OT ama -rbayrak ne anlama geliyor? Görüyorum ki xargsbir -Rtartışma var ama hakkında hiçbir şey bulamadık -r. Yani, teorik olarak, nasıl xargsçalıştığını doğru hatırlarsam , onsuz -rda çalışmalıdır.
Aldo 'xoen' Giambelluca

Bu cevabı beğendim. Birkaç not (gerçekten belirten). Son boruyu ve son komutu kaldırarak hangi dalların silineceğini "önizlemek" mümkündür | xargs git branch -d. Ayrıca, -r( --remotes) seçeneğini kaldırarak git branch -dyalnızca yerel şubeleri temizleriz (varsayılan olarak git branchuzak şubeleri göstermediği düşünülebilir ).
Aldo 'xoen' Giambelluca

Teşekkürler! Tam da ihtiyacım olan buydu. Diğer çözümler, budanmış yerel dalları orada kaldırmak için uzaktan kumandaya itmeyi önerir, ancak uzaktan kumanda kaldırıldığında veya artık mevcut olmadığında bu yardımcı olmaz. Bu yaklaşım, artık erişemediğim uzak dallara yapılan yerel başvuruları kaldırdı.
cautionbug

@aldo, hakkında xargs -r, yani --no-run-if-empty, bu bir GNU uzantısı anlamına gelir, burada güzel bir açıklama .
ryenus

4

Silme her zaman zorlu bir iştir ve tehlikeli olabilir !!! Bu nedenle, ne olacağını görmek için önce aşağıdaki komutu yürütün:

git push --all --prune --dry-run

Yukarıdaki gibi yaptığınızda git, aşağıdaki komut yürütülürse ne olacağının bir listesini sağlar.

Ardından, yerel deponuzda bulunmayan uzak repodaki tüm dalları kaldırmak için aşağıdaki komutu çalıştırın:

git push --all --prune

10
Bu komut tehlikeli görünüyor ... İstediğimi silmeyi başardı (ve yukarıdaki cevapların en az dördüyle yapamadı). Ama aynı zamanda dört diğer dev dalını da sildi. Git kesinlikle berbat ...
jww

2
Bu şubeler bölgenizde bulunmamış olmalıdır. Ancak her şey kaybolmaz. Git commit, Git reflog ve ardından git reset --hard <checksum>. Gerçekten bununla herhangi bir taahhüt (aka save) ve diğerleri için yapabilirsiniz. Şube sadece bir etikettir, etiketin silinmesi kaydetmeyi silmez ... sonsuza kadar bir sağlama toplamı olur. Yardım edebilirsem bana haber ver
Timothy LJ Stewart

3
Tabii ki, git'in çöp toplayıcısı sonunda şubeler tarafından referans verilmeyen taahhütleri kaldıracağından bunları oldukça hızlı bir şekilde kurtarmak istersiniz.
Andrew

1
-nBu komuta eklemek (kuru çalışma) iyidir, böylece değişiklikleri önizleyebilirsiniz ve sonra her şey yolundaysa tekrar olmadan arayın -n.
mati865

1
@GuiWeinmann ile aynı fikirde - Bu, özellikle en azından kuru çalışma modunda çalıştırmak için belirli bir açıklama olmadan çok tehlikelidir.
Vivek M. Chawla

2

İşte SourceTree (V2.3.1) ile yapmak için yapılması gerekenler:
1. tıklayın Getirme
2. Kontrolü "Erik izleme dalları ..."
3. OK tuşuna basın
4. 😀

resim açıklamasını buraya girin


1

Buraya bir cevap eklemem gerekecek, çünkü diğer cevaplar ya davamı kapsamıyor ya da gereksiz yere karmaşık. Diğer geliştiricilerle github kullanıyorum ve sadece uzaktan kumandaları bir github PR'dan silinen tüm yerel şubelerin makinemden bir seferde silinmesini istiyorum. Hayır, git branch -r --mergedyerel olarak birleştirilmeyen dalları veya hiç birleştirilmemiş (terk edilmiş) vb. Alanları kapsamaz, bu nedenle farklı bir çözüme ihtiyaç vardır.

Her neyse, diğer adımlardan aldığım ilk adım:

git fetch --prune

Kuru bir çalışma git remote prune originbenim durumumda aynı şeyi yapacak gibi görünüyordu, bu yüzden basit tutmak için en kısa versiyonu ile gittim.

Şimdi a git branch -v, kumandaları silinmiş olan dalları işaretlemelidir [gone]. Bu nedenle, tek yapmam gereken:

git branch -v|grep \\[gone\\]|awk '{print $1}'|xargs -I{} git branch -D {}

Bu kadar basit, yukarıdaki senaryo için istediğim her şeyi siler.

Daha az yaygın xargssözdizimi, Linux'a ek olarak Mac ve BSD üzerinde de çalışabilmesidir. Dikkatli olun, bu komut kuru bir çalışma değildir, bu nedenle olarak işaretlenen tüm dalları zorla siler [gone]. Açıkçası, bu git olmak hiçbir şey sonsuza kadar gitmez, eğer istediğinizi hatırladığınız şubelerin silindiğini görürseniz, onları her zaman silme işlemini geri alabilirsiniz (yukarıdaki komut, silme işlemindeki karmalarını listeleyecektir, bu yüzden basit git checkout -b <branch> <hash>.


0
# First use prune --dry-run to filter+delete the local branches
git remote prune origin --dry-run \
  | grep origin/ \
  | sed 's,.*origin/,,g' \
  | xargs git branch -D

# Second delete the remote refs without --dry-run
git remote prune origin

Aynı şubeleri yerel ve uzak referanslardan (bu örnekte origin).

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.