2016-04-05 12 views
8

Conosco how to delete all local branches that have been merged. Tuttavia, e credo che ciò sia dovuto alla nuova funzionalità di Github pull request squash and merge, mi ritrovo a lasciare molti rami locali che non sono raggruppati, ma se uniti in master non comportano alcuna modifica.Come posso cancellare tutti i rami locali che non comporterebbero cambiamenti se uniti in master?

Come posso potare questi rami locali, ovvero quelle diramazioni locali che non sono necessariamente state unite, ma non influiscono sul master (o, più genericamente, sul ramo corrente)?

+0

Ti aspetti davvero di avere molti rami locali attorno ai quali non ci sono cambiamenti rispetto al master? Questo non implica che qualcuno abbia creato un ramo e non abbia fatto nulla con esso? –

+0

Il processo è: creo un ramo locale, apporto le modifiche, lo spingo in remoto, invio un PR, il PR viene unito a uno squash in master, faccio avanzare rapidamente il mio master locale e ... il mio ramo locale rimane non diviso ('git branch -d' non lo elimina), ma non ha modifiche rispetto al master (' git diff branch_name' non ha risultati). Quindi, se avessi fatto 10 PR, avrò 10 filiali locali non raggruppate senza modifiche. – Claudiu

+0

Non mi piace questo flusso di lavoro. Perché non basta uccidere il ramo dopo averlo fuso in 'master'? –

risposta

3

Non c'è una soluzione perfetta ma puoi avvicinarti, forse abbastanza vicino.

Assicurarsi di iniziare con un albero di lavoro pulito e un indice (vedere require_clean_work_tree in git-sh-setup).

Per ogni ramo candidato $branch che potrebbero essere elimina-grado:

  1. trovare la sua destinazione di unione (presumibilmente merge_target=$(git config --get branch.${branch}.merge)). Controlla il target di fusione.
  2. Unire con --no-commit; oppure nel passaggio 1, controlla con --detach in modo da ottenere un commit che puoi abbandonare, se l'unione ha esito positivo.
  3. Verificare se git pensa che l'unione sia riuscita e, in tal caso, se l'albero attuale corrisponde all'albero precedente, cioè non ha apportato alcuna modifica. Se riesci a testare le corrispondenze esatte e se permetti il ​​commit (via --detach), puoi fare questo ultimo test in modo molto semplice, senza alcuna differenza: esegui sia git rev-parse HEAD^{tree} e git rev-parse HEAD^^{tree} e vedi se producono lo stesso hash. Se non si consente il commit, è ancora possibile git diff il commit corrente (HEAD) contro l'unione proposta. Se è necessario rimuovere un po 'di rumore dal diff (ad esempio, i file di configurazione che non dovrebbero essere, ma sono comunque nei commit), questo ti dà un posto dove farlo.
  4. Reset (git merge --abort; git reset --hard HEAD; git clean -f o simile, a seconda di come si è deciso di implementare i passaggi 1-3). Questo è solo lo scopo di rendere il tuo albero di lavoro e l'indice di nuovo pulito, per il prossimo passaggio.
  5. Se l'unione nel passaggio 3 ha funzionato e non ha apportato modifiche, è possibile eliminare il ramo locale. Altrimenti, tienilo.

In sostanza, questo è "effettivamente fare l'unione e vedere cosa succede", solo completamente automatizzato.


Questa notazione sembra un po 'strano, ma è solo HEAD^ -il primo genitore del HEAD -followed da ^{tree}. Le ortografie alternative potrebbero essere più facili da leggere: HEAD~1^{tree} o ${merge_target}^tree, dove ${merge_target} è il ramo che hai controllato al passaggio 1. Si noti che questo presuppone l'unione riuscita. Il risultato dell'unione è nello stato di uscita di git merge: zero significa riuscito, non zero significa non riuscito e necessita di assistenza manuale, presumibilmente a causa di un conflitto di unione.

+0

Hmm Sono incuriosito! Sembra che dovrebbe essere sufficiente per me produrre un comando che faccia ciò che mi piace automaticamente. Ora che sto usando Git di più, sto arrivando ad apprezzarlo più come un linguaggio di codifica di sorta, invece di un sistema di controllo di versione monolitico - se so come funziona, posso usare il linguaggio (cioè il built-in comandi) per scrivere nuovi comandi con le funzionalità che voglio (ovvero le funzioni in altre lingue). – Claudiu

+0

Sì, in particolare i comandi "plumbing" di git sono pensati per lo scripting. Il primo livello 'git merge' non è in realtà un comando idraulico, ma dovrà servire qui. Il problema principale con uno script che fa questo è che potrebbe eliminare i rami su cui hai intenzione di lavorare, ma non hai ancora iniziato a lavorare, quindi potresti voler filtrare un po 'i tuoi candidati in quel caso. – torek

0

Se si esegue git "branch -v", i rami di rilevamento che hanno modifiche avranno "in anticipo" scritto accanto a essi.

Le altre due opzioni: "dietro" e se non viene scritto nulla, significa che i rami non hanno modifiche che influenzeranno i rami tracciati.

È quindi possibile eseguire "git fetch" per aggiornare i rami di monitoraggio remoto, quindi analizzare i risultati "git branch -v" per capire quali rami non hanno modifiche e quali rami hanno.

Problemi correlati