tutorial - guida git pdf




Come posso cancellare tutti i rami Git che sono stati uniti? (20)

Ho molti rami Git. Come faccio a eliminare i rami che sono già stati uniti? C'è un modo semplice per eliminarli tutti invece di eliminarli uno per uno?


A partire dal 2018.07

Aggiungi questo alla sezione [alias] di ~/.gitconfig :

sweep = !"f() { git branch --merged | egrep -v \"(^\\*|master|dev)\" || true | xargs git branch -d; }; f"

Ora puoi semplicemente chiamare git sweep per eseguire la pulizia necessaria.


Come eliminare i rami uniti nella console di PowerShell

git branch --merged | %{git branch -d $_.Trim()}

Vedi GitHub per Windows


AGGIORNARE:

Puoi aggiungere altri rami da escludere come master e dev se il tuo flusso di lavoro ha quelli come possibile antenato. Di solito mi distacco da un tag "sprint-start" e master, dev e qa non sono antenati.

Per eliminare tutti i rami locali già uniti nel ramo attualmente ritirato:

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

Puoi vedere che master e dev sono esclusi nel caso in cui siano antenati.

È possibile eliminare un ramo locale unito con:

git branch -d branchname

Se non è unito, usa:

git branch -D branchname

Per eliminarlo dal telecomando nelle vecchie versioni di Git, utilizzare:

git push origin :branchname

Nelle versioni più recenti di Git usi:

git push --delete origin branchname

Una volta eliminato il ramo dal telecomando, è possibile eliminare i rami di monitoraggio remoto con:

git remote prune origin

o potare i singoli rami di localizzazione remota, come suggerisce l'altra risposta, con:

git branch -dr branchname

Spero che questo ti aiuti.


Basta estendere la risposta di Adam un po ':

Aggiungi questo alla tua configurazione Git eseguendo git config -e --global

[alias]
    cleanup = "!git branch --merged | grep  -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d"

E poi puoi cancellare tutti i rami uniti locali facendo una semplice git cleanup .


Ho usato la risposta di Adam per anni. Detto questo, ci sono alcuni casi in cui non si comportava come mi aspettavo:

  1. i rami che contenevano la parola "maestro" sono stati ignorati, ad esempio "notmaster" o "masterful", piuttosto che solo il ramo principale
  2. i rami che contenevano la parola "dev" sono stati ignorati, ad esempio "dev-test", piuttosto che solo il ramo dev
  3. eliminazione di rami raggiungibili dal HEAD del ramo corrente (ovvero, non necessariamente master)
  4. in stato HEAD distaccato, eliminando ogni ramo raggiungibile dal commit corrente

1 e 2 erano semplici da indirizzare, con solo una modifica alla regex. 3 dipende dal contesto di ciò che si desidera (vale a dire solo eliminare i rami che non sono stati uniti in master o contro il ramo corrente). 4 ha il potenziale di essere disastroso (anche se recuperabile con git reflog ), se involontariamente lo si è verificato in stato di TESTA distaccato.

Infine, volevo che tutto questo fosse in un one-liner che non richiedesse uno script separato (Bash | Ruby | Python).

TL; DR

Crea un "sweep" alias git che accetta un flag -f opzionale:

git config --global alias.sweep '!f(){ git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d; }; f'

e invocilo con:

git sweep

o:

git sweep -f

La risposta lunga e dettagliata

È stato più facile per me creare un esempio di repository git con alcuni rami e mi impegno a testare il comportamento corretto:

Crea un nuovo repository git con un singolo commit

mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"

Crea alcuni nuovi rami

git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
  bar
  develop
  foo
* master
  masterful
  notmaster

Comportamento desiderato: selezionare tutti i rami uniti tranne: master, develop o current

Il regex originale manca i rami "magistrale" e "notmaster":

git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
  bar

Con la regex aggiornata (che ora esclude "develop" piuttosto che "dev"):

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster

Passa al ramo foo, fai un nuovo commit, quindi controlla un nuovo ramo, foobar, basato su foo:

echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"

Il mio attuale ramo è foobar, e se rieseguo il comando precedente per elencare i rami che voglio cancellare, il ramo "foo" è incluso anche se non è stato fuso in master:

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  masterful
  notmaster

Tuttavia, se eseguo lo stesso comando su master, il ramo "foo" non è incluso:

git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

E questo è semplicemente perché git branch --merged valore predefinito il HEAD del ramo corrente se non diversamente specificato. Almeno per il mio flusso di lavoro, non voglio eliminare i rami locali a meno che non siano stati uniti al master, quindi preferisco la seguente variante:

git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Stato HEAD distaccato

Affidarsi al comportamento predefinito di git branch --merged ha conseguenze ancora più significative nello stato di HEAD distaccato:

git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  foobar
  masterful
  notmaster

Questo avrebbe cancellato il ramo su cui mi trovavo, "foobar" e "foo", che non è certo il risultato desiderato. Con il nostro comando revisionato, tuttavia:

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Una riga, inclusa l'eliminazione effettiva

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d

Tutto racchiuso in un git alias "sweep":

git config --global alias.sweep '!f(){ git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d; }; f'

L'alias accetta un flag facoltativo -f . Il comportamento predefinito consiste nell'eliminare solo i rami che sono stati uniti in master, ma il flag -f cancellerà i rami che sono stati uniti nel ramo corrente.

git sweep
Deleted branch bar (was 9a56952).
Deleted branch masterful (was 9a56952).
Deleted branch notmaster (was 9a56952).
git sweep -f
Deleted branch foo (was 2cea1ab).

Io uso uno schema di denominazione esque git-flow, quindi questo funziona in modo molto sicuro per me:

git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d

Cerca fondamentalmente i commit uniti che iniziano con la fix/ stringhe o con la feature/ .


La soluzione accettata è piuttosto buona, ma presenta il problema che elimina anche i rami locali che non erano stati ancora uniti in un telecomando.

Se guardi l'output di te vedrai qualcosa di simile

$ git branch --merged master -v
  api_doc                  3a05427 [gone] Start of describing the Java API
  bla                      52e080a Update wording.
  branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1
  initial_proposal         6e59fb0 [gone] Original proposal, converted to AsciiDoc.
  issue_248                be2ba3c Skip unit-for-type checking. This needs more work. (#254)
  master                   be2ba3c Skip unit-for-type checking. This needs more work. (#254)

I rami bla e issue_248 sono rami locali che verrebbero cancellati silenziosamente.

Ma puoi anche vedere la parola [gone] , che indica i rami che sono stati spinti su un telecomando (che ora è scomparso) e quindi denotano che i rami possono essere cancellati.

La risposta originale può quindi essere modificata in (divisa in multilinea per una lunghezza della linea più breve)

git branch --merged master -v | \
     grep  "\\[gone\\]" | \
     sed -e 's/^..//' -e 's/\S* .*//' | \
      xargs git branch -d

per proteggere i rami non ancora uniti. Non è necessario nemmeno il grepping per il master per proteggerlo, in quanto ha un origine remota e non si presenta come andato.


Non c'è alcun comando in Git che lo farà automaticamente. Ma puoi scrivere uno script che usa i comandi Git per darti quello che ti serve. Questo potrebbe essere fatto in molti modi a seconda del modello di ramificazione che stai utilizzando.

Se hai bisogno di sapere se un ramo è stato fuso in master, il seguente comando non produrrà output se myTopicBranch è stato unito (ovvero puoi eliminarlo)

$ git rev-list master | grep $(git rev-parse myTopicBranch)

È possibile utilizzare il comando ramo Git e analizzare tutti i rami in Bash e fare un ciclo for su tutti i rami. In questo ciclo controlli con il comando precedente se puoi cancellare il ramo o no.


Per eliminare i rami locali che sono stati uniti al ramo master, sto usando il seguente alias ( git config -e --global ):

cleanup = "!git branch --merged master | grep -v '^*\\|master' | xargs -n 1 git branch -D"

Sto usando git branch -D per evitare error: The branch 'some-branch' is not fully merged. messaggi mentre il mio checkout corrente è diverso dal master branch.


Per eliminare tutti i rami su remoto già uniti:

git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin

Nelle versioni più recenti di Git

git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin

Per quelli di voi che sono su Windows e preferiscono gli script di PowerShell, ecco uno che cancella i rami unificati locali:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}

Prova il seguente comando:

git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Usando git rev-parse otterrà il nome del ramo corrente per poterlo escludere. Se hai ricevuto l'errore, significa che non ci sono rami locali da rimuovere.

Per fare lo stesso con i rami remoti (cambia origin con il tuo nome remoto), prova:

git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)

Se hai più telecomandi, aggiungi l' grep origin | prima di cut per filtrare solo l' origin .

Se il comando precedente non riesce, provare prima a eliminare i rami uniti di tracciamento remoto:

git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Quindi git fetch nuovamente il telecomando e usa di nuovo il precedente comando git push -vd .

Se lo stai usando spesso, ~/.gitconfig considerazione l'aggiunta di alias nel tuo file ~/.gitconfig .

Nel caso in cui hai rimosso alcuni rami per errore, usa git reflog per trovare i commit persi.


Questo funziona anche per eliminare tutti i rami uniti tranne il master.

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d

Qui sotto la query funziona per me

for branch in  `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print$1}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done

e questo filtra ogni dato ramo nella pipe di grep.

Funziona bene su http clone, ma non così bene per la connessione ssh.


Scrivi uno script in cui Git controlla tutti i rami che sono stati uniti per diventare master.

Quindi fai il git checkout master .

Infine, elimina i rami uniti.

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git checkout $branchnew
done

git checkout master

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git push origin --delete $branchnew
done

Se desideri eliminare tutti i rami locali già integrati nel ramo in cui ti trovi al momento, ho creato un comando sicuro, in base alle risposte precedenti:

git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d

Questo comando non influirà sul ramo attuale o sul ramo principale. Ti dirà anche cosa sta facendo prima di farlo, usando il flag -t di xargs.


Sulla base di alcune di queste risposte ho realizzato il mio script Bash per farlo anche io!

Usa il git branch --merged e git branch -d per eliminare i rami che sono stati uniti e ti richiede per ciascuno dei rami prima di eliminarli.

merged_branches(){
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  for branch in $(git branch --merged | cut -c3-)
    do
      echo "Branch $branch is already merged into $current_branch."
      echo "Would you like to delete it? [Y]es/[N]o "
      read REPLY
      if [[ $REPLY =~ ^[Yy] ]]; then
        git branch -d $branch
      fi
  done
}

Usando Git versione 2.5.0:

git branch -d `git branch --merged`

Versione alias della risposta aggiornata di Adam :

[alias]
    branch-cleanup = "!git branch --merged | egrep -v \"(^\\*|master|dev)\" | xargs git branch -d #"

Inoltre, consulta questa risposta per suggerimenti pratici su come eseguire l'escape di alias complessi.






feature-branch