2010-07-06 16 views
461

Ecco il mio flusso di lavoro git.ripulire vecchi rami di git remoti

Lavoro da due computer diversi (A e B) e memorizzo un comune git remoto nella directory dropbox.

Diciamo che ho due rami master e sviluppo. Entrambi stanno monitorando le loro controparti remote origine/master e origine/sviluppo.

Ora, mentre sul computer A, cancello ramo devel - sia locali che remote - come segue:

git push origin :heads/devel 

git branch -d devel 

Ora, se faccio git branch -a sul computer A, ottengo

master 
origin/HEAD 
origin/master 

ora vai al computer B. Fai git fetch. Posso rimuovere il ramo di devel locale da

git branch -d devel 

Ma non riesco a rimuovere il ramo di devel remoto.

git push origin :heads/devel 

error: unable to push to unqualified destination: heads/proxy3d 
The destination refspec neither matches an existing ref on the remote nor 
begins with refs/, and we are unable to guess a prefix based on the source ref. 
fatal: The remote end hung up unexpectedly 

Facendo git branch -a elenca ancora origine/devel nelle filiali remote.

Come è possibile pulire l'ingresso remoto di devel dalla macchina B?

+3

Mi è stato detto da chi l'ha provato, che i repository git nelle cartelle Dropbox sono un po 'fragili (ma senza dettagli aggiuntivi). –

+4

@ ThorbjørnRavnAndersen probabilmente perché devi attendere che si sincronizzi completamente ogni volta che effettui il commit, prima di poter essere sicuro che sia sicuro sull'altro (e un'altra sincronizzazione è necessaria anche in quel momento). – ataulm

risposta

862

Innanzitutto, qual è il risultato di git branch -a sulla macchina B?

In secondo luogo, è già stato eliminato heads/devel su origin, ecco perché non è possibile eliminarlo dalla macchina B.

Prova

git branch -r -d origin/devel 

o

git remote prune origin 

o

git fetch origin --prune 

e sentiti libero di aggiungere --dry-run alla fine della tua istruzione git per vedere il risultato dell'esecuzione senza eseguirlo.

+5

'git branch -r -d origin/devel' ha funzionato per me. Grazie. ora che ho letto la pagina di manuale di 'git remote prune', immagino che dovrebbe funzionare anche. Lo proverò la prossima volta. – Jayesh

+34

'git remote prune origin' ha funzionato per me =>' * [potato] origin/my-old-branch' –

+0

Grazie. Ho ricevuto il seguente messaggio "Il refspec di destinazione non corrisponde a un ref esistente sul telecomando, né ..." quando ho provato a eliminare un ramo remoto. Quindi ho usato 'git branch -r -d origin/devel' e il ramo è stato cancellato –

13

Ecco lo script di bash che può farlo per voi. È una versione modificata dello script http://snippets.freerobby.com/post/491644841/remove-merged-branches-in-git. La mia modifica consente di supportare diverse postazioni remote.

#!/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

Questo si è rotto su un ramo chiamato "origine/funzionalità/mybranch", non so perché. –

+0

Il problema è nei due 'sed's. Sostituisci 'sed 's/\ (. * \) \/\ (. * \)/\ 1/g'' di' sed' s/\ ([^ /] * \) \/\ (. * \)/\ 1/g'' –

2

Ecco come farlo con SourceTree (v2.3.1):
1. Fare clic su Fetch
2. Controllare "rami di tracciamento Potare ..."
3. Premere OK
4.

enter image description here

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

Questo rimuovere tutti i rami dal repository remoto non sul repository locale. Se ti piace quello che vedi, esegui nuovamente il comando senza --dry-run.

In risposta ai commenti: Intrinsecamente, l'atto di eliminazione è pericoloso, quindi sentitevi liberi di aggiungere --dry-run e leggere man git push.

+7

Questo comando sembra essere pericoloso ... È riuscito a cancellare quello che volevo (e non poteva fare con almeno quattro delle risposte sopra). Ma ha anche cancellato altri quattro rami di sviluppo. Git fa assolutamente schifo ... – jww

+1

Questi rami non devono essere stati sul tuo locale. Tuttavia non tutto è perduto. Git commit, Git reflog e quindi git reset --hard . Puoi letteralmente qualsiasi commit (aka save) e altri con questo. Branch è solo un'etichetta, l'eliminazione dell'etichetta non cancella il salvataggio ... avrà sempre un checksum. Fammi sapere se posso aiutare –

+2

Ovviamente, ti consigliamo di recuperarli abbastanza rapidamente poiché il garbage collector di git alla fine rimuoverà i commit non riferiti dai rami. – Andrew

5

Questo comando eseguirà il "funzionamento a secco" eliminando tutti i rami uniti (origin), ad eccezione di master. È possibile cambiare la situazione, o, aggiungere rami supplementari dopo padrone: 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 

Se si guarda bene, rimuovere il --dry-run. Inoltre, potresti provare prima questo su una forcella.

+0

Nizza. Il mio tweak usando perl al posto del primo xargs + awk: git branch -r --merged | origine grep | grep -v '>' | grep -v master | perl -lpe '($ junk, $ _) = split (/ \ //, $ _, 2)' | xargs git push origin --delete – Andrew

29

Considerare per eseguire:

git fetch --prune 

Su base regolare in ogni repo per rimuovere i rami locali che sono stati il ​​monitoraggio di un ramo remoto che elimina (non esiste più in pronti contro termine GIT remoto).

Questo può essere ulteriormente semplificato dalla

git config remote.origin.prune true 

questa è una regolazione per-repo che renderà ogni futuro automaticamente prugna.

Per impostare questa funzione per l'utente, si può anche modificare il .gitconfig globale e aggiungere

[fetch] 
    prune = true 

Tuttavia, è consigliabile che questo viene fatto utilizzando il seguente comando:

git config --global fetch.prune true 

o per applicarlo a livello di sistema (non solo per l'utente)

git config --system fetch.prune true 
1

Se git branch -r sho ws un sacco di filiali remote-tracking che non siete interessati e che si desidera rimuovere dal loro solo locale, utilizzare il seguente comando:

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

Una versione più sicura sarebbe quella di rimuovere quelli unici fusi:

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

Questo potrebbe essere utile per i progetti di grandi dimensioni, in cui non sono necessari i rami di funzionalità di altri membri del team ma molte sequenze di rilevamento remoto recuperate sul clone iniziale.

E questo passo da solo è incompleta perché quelle eliminate filiali remote-tracking avrebbe mostrato di nuovo al successivo git fetch.

Per interrompere il recupero quei rami remote-tracking è necessario specificare esplicitamente gli arbitri a prendere in .git/config:

[remote "origin"] 
    # fetch = +refs/heads/*:refs/remotes/origin/* 
    fetch = +refs/heads/master:refs/remotes/origin/master 
    fetch = +refs/heads/develop:refs/remotes/origin/develop 

Nell'esempio precedente abbiamo recuperare solo master e develop rami, sentitevi liberi e aggiungi il tuo.