Elencando ogni filiale e la data dell'ultima revisione in Git


138

Devo eliminare i rami vecchi e non mantenuti dal nostro repository remoto. Sto cercando di trovare un modo per elencare i rami remoti in base alla loro ultima data di modifica e non posso.

C'è un modo semplice per elencare i rami remoti in questo modo?



3
Le risposte a: stackoverflow.com/questions/5188320/… sono tutte migliori delle risposte qui
Software Engineer

Risposte:


172

commandlinefu ha 2 proposizioni interessanti:

for k in `git branch | perl -pe s/^..//`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

o:

for k in `git branch | sed s/^..//`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k --`\\t"$k";done | sort

Questo è per le filiali locali, in una sintassi Unix. Usando git branch -r, puoi anche mostrare rami remoti:

for k in `git branch -r | perl -pe 's/^..(.*?)( ->.*)?$/\1/'`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

Michael Forrest menziona nei commenti che zsh richiede escape per l' sedespressione:

for k in git branch | perl -pe s\/\^\.\.\/\/; do echo -e git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1\\t$k; done | sort -r 

Kontinuity aggiunge nei commenti :

Se vuoi aggiungerlo a zshrc è necessaria la seguente via di fuga.

alias gbage='for k in `git branch -r | perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r'

In più righe:

alias gbage='for k in `git branch -r | \
  perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; \
  do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | \
     head -n 1`\\t$k; done | sort -r'

Nota: la risposta di n8tr , basata su è più pulita. E più veloce . Vedi anche " Opzione solo nome per ? "git for-each-ref refs/heads
git branch --list

Più in generale, il tripleee ci ricorda nei commenti :

  • Preferisce la $(command substitution)sintassi moderna rispetto alla sintassi backtick obsoleta.

(Ho illustrato questo punto nel 2014 con " Qual è la differenza tra $(command)e `command`nella programmazione della shell? ")

  • Non leggere le righe confor .
  • Probabilmente passa a git for-each-ref refs/remoteper ottenere i nomi delle filiali remote in formato leggibile da una macchina

1
@hansen j: interessante, no? È stato lanciato pochi mesi dopo l'uscita pubblica di Stack Overflow ( codeinthehole.com/archives/… ) ed è stato in qualche modo ispirato da SO. Vedi anche commandlinefu.com/commands/tagged/67/git per più git
commandlinefu

Questa risposta il via a stackoverflow.com/questions/5188320/…. :)
Spundun,

@SebastianG non sono sicuro: sarebbe una buona domanda a sé stante.
VonC

+1 Abbastanza fantastico come puoi aggiungere /jsonalla fine di qualsiasi URL commandlinefu.com e otterrai tutti i comandi come JSON.
Noah Sussman,

1
@tripleee Grazie. Ho modificato la risposta e incluso i tuoi commenti per una maggiore visibilità.
VonC,

121

Ecco cosa uso:

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads

Questo è l'output:

2014-01-22 11:43:18 +0100       refs/heads/master
2014-01-22 11:43:18 +0100       refs/heads/a
2014-01-17 12:34:01 +0100       refs/heads/b
2014-01-14 15:58:33 +0100       refs/heads/maint
2013-12-11 14:20:06 +0100       refs/heads/d/e
2013-12-09 12:48:04 +0100       refs/heads/f

Per le filiali remote, basta usare "refs / telecomandi" invece di "refs / head":

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/remotes

Sulla base della risposta di n8tr , se sei interessato anche all'ultimo autore sul ramo e se hai lo strumento "colonna" disponibile, puoi usare:

git for-each-ref --sort='-committerdate:iso8601' --format='%(committerdate:relative)|%(refname:short)|%(committername)' refs/remotes/ | column -s '|' -t

Che ti darà:

21 minutes ago  refs/remotes/a        John Doe
6 hours ago     refs/remotes/b        Jane Doe
6 days ago      refs/remotes/master   John Doe

Potresti voler chiamare "git fetch --prune" prima di avere le informazioni più recenti.


5
Buon uso di for-each-ref e delle opzioni di formato. +1. Sembra più facile dei comandi a cui faccio riferimento nella mia risposta.
VonC,

2
ottimizzando un po ': ------- git for-each-ref --sort =' - authordate: iso8601 '--format ='% (authordate: relative)% 09% (refname: short) 'refs / heads ------- ti dà una data relativa ed elimina i
refs

1
Per coloro a cui non è immediatamente ovvio, penso che questo mostri informazioni. rigorosamente per le filiali locali.
hBrent,

@hBrent hai ragione, non ha risposto esattamente alla domanda. Ho modificato la mia risposta di conseguenza.
ocroquette,

Questo ordina ed elenca i rami per authordate(che sembra essere quando il ramo è stato creato per la prima volta?). Se cambi authordatea committerdate, vedrai le date del commit più recente in ogni ramo. In questo modo:git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads
Logan Besecker,

23

Partendo da Olivier Croquette , mi piace usare una data relativa e abbreviare il nome della filiale in questo modo:

git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads

Che ti dà un output:

21 minutes ago  nathan/a_recent_branch
6 hours ago        master
27 hours ago    nathan/some_other_branch
29 hours ago    branch_c
6 days ago      branch_d

Consiglio di creare un file Bash per aggiungere tutti i tuoi alias preferiti e quindi condividere lo script con il tuo team. Ecco un esempio per aggiungere solo questo:

#!/bin/sh

git config --global alias.branches "!echo ' ------------------------------------------------------------' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------'"

Quindi puoi semplicemente farlo per ottenere un elenco di filiali locali ben formattato e ordinato:

git branches

20

Solo per aggiungere al commento di @VonC, prendi la tua soluzione preferita e aggiungila al tuo elenco di alias ~ / .gitconfig per comodità:

[alias]  
    branchdate = !git for-each-ref --sort='-authordate' --format='%(refname)%09%(authordate)' refs/heads | sed -e 's-refs/heads/--'

Quindi un semplice "git branchdate" stampa l'elenco per te ...


3
+1 per mostrare come usarlo con .gitconfig! Inoltre, ho cambiato la stringa di formato in: --format='%(authordate)%09%(objectname:short)%09%(refname)'che ottiene anche l'hash corto di ogni ramo.
Noah Sussman,

Bello. Aggiungerei "| tac" alla fine per ordinarlo in ordine inverso in modo che i rami toccati di recente siano rapidamente visibili.
Ben

1
Non è necessario | tac, solo --sort='authordate'invece di-authordate
Kristján

4

Ecco cosa mi è venuto in mente dopo aver esaminato anche questo .

for REF in $(git for-each-ref --sort=-committerdate --format="%(objectname)" \
    refs/remotes refs/heads)
do
    if [ "$PREV_REF" != "$REF" ]; then
        PREV_REF=$REF
        git log -n1 $REF --date=short \
            --pretty=format:"%C(auto)%ad %h%d %s %C(yellow)[%an]%C(reset)"
    fi
done

Il PREV_REFcontrollo consiste nel rimuovere i duplicati se più di un ramo punta allo stesso commit. (Come in un ramo locale che esiste anche nel telecomando.)

NOTA che per la richiesta OP, git branch --mergede git branch --no-mergedsono utili per identificare quali rami possono essere facilmente eliminati.

[ https://git-scm.com/docs/git-branch]


3

Filiali remote ordinate e l'ultima data di commit per ogni filiale.

for branch in `git branch -r | grep -v HEAD`;do echo -e `git show --format="%ci %cr" $branch | head -n 1` \\t$branch; done | sort -r

1
Grazie per aver risposto alla domanda OP relativa al telecomando.
arcseldon,

1

Ho fatto due varianti, basandomi sulla risposta di VonC .

La mia prima variante:

for k in `git branch -a | sed -e s/^..// -e 's/(detached from .*)/HEAD/'`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`;done | sort | column -t -s "|"

Gestisce i rami locali e remoti ( -a), gestisce lo stato a testa staccata (il comando sed più lungo, sebbene la soluzione sia un po 'rozza - sostituisce semplicemente le informazioni sul ramo staccato con la parola chiave HEAD), aggiunge l'oggetto del commit (% s ) e inserisce le cose in colonne tramite caratteri letterali di pipe nella stringa di formato e passando il risultato finale a column -t -s "|". (Puoi usare qualunque cosa come separatore, purché sia ​​qualcosa che non ti aspetti nel resto dell'output.)

La mia seconda variante è piuttosto confusa, ma volevo davvero qualcosa che abbia ancora un indicatore di "questo è il ramo in cui ti trovi attualmente" come fa il comando branch.

CURRENT_BRANCH=0
for k in `git branch -a | sed -e 's/\*/CURRENT_BRANCH_MARKER/' -e 's/(detached from .*)/HEAD/'`
do
    if [ "$k" == 'CURRENT_BRANCH_MARKER' ]; then
        # Set flag, skip output
        CURRENT_BRANCH=1
    elif [ $CURRENT_BRANCH == 0 ]; then
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`
    else
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset* %Cgreen$k%Creset |%s" $k --`
        CURRENT_BRANCH=0
    fi
done | sort | column -t -s "|"

Questo trasforma il *segno che contrassegna il ramo corrente in una parola chiave, e quando il corpo del ciclo vede la parola chiave invece imposta un flag e non produce nulla. Il flag viene utilizzato per indicare che è necessario utilizzare una formattazione alternativa per la riga successiva. Come ho detto, è totalmente confuso, ma funziona! (Principalmente. Per qualche ragione, la mia ultima colonna si sta superando nella linea di diramazione corrente.)


Sfortunatamente le informazioni contenute nella risposta di VonCs non sono un'ottima base per gli script. Vedi qui git-blame.blogspot.com/2013/06/…
Andrew C

Hmm. Ciò mostra un modo per ottenere il nome del ramo corrente, se ha un nome. Esiste un modo [preferito] per ottenere un elenco di filiali intuitivo? (E un modo per distinguere il ramo attuale, sia da
quell'output

git for-each-refè il modo intuitivo di elaborare i rami. Dovresti eseguire il ref simbolico una volta per ottenere il ramo corrente.
Andrew C,

+1 per lo sforzo, ma quella era davvero una mia vecchia risposta. stackoverflow.com/a/16971547/6309 o (più completo) stackoverflow.com/a/19585361/6309 può comportare meno "sed".
VonC,

1

Ho fatto un semplice alias, non sono sicuro se questo è esattamente ciò che è stato chiesto, ma è semplice

Ho fatto questo perché volevo elencare tutti i rami, non solo i miei rami locali, che solo i comandi sopra fanno

alias git_brs="git fetch && git branch -av --format='\''%(authordate)%09%(authordate:relative)%09%(refname)'\'"

Puoi grep originpassare sopra per ottenere solo origini

Questo elenca tutti i rami insieme all'ultima data modificata, mi aiuta a decidere quale dovrei estrarre per l'ultima versione

Ciò si traduce nel seguente tipo di display

Wed Feb 4 23:21:56 2019 +0230   8 days ago      refs/heads/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/heads/master
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/heads/bar
Wed Feb 11 16:34:00 2019 +0230  2 days ago      refs/heads/xyz
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/HEAD
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/remotes/origin/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/master
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/bar
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/xyz

Prova e fammi sapere se ha aiutato, felice gitting


Bello e semplice. Nessuna salsa speciale.
MrMas

0

Oppure puoi usare il mio script PHP, https://gist.github.com/2780984

#!/usr/bin/env php
<?php
    $local = exec("git branch | xargs $1");
    $lines = explode(" ", $local);
    $limit = strtotime("-2 week");
    $exclude = array("*", "master");
    foreach ($exclude as $i) {
        $k = array_search($i, $lines);
        unset($lines[$k]);
    }
    $k = 0;
    foreach ($lines as $line) {
        $output[$k]['name'] = $line;
        $output[$k]['time'] = exec('git log '.$line.' --pretty=format:"%at" -1');
        if ($limit>$output[$k]['time']) {
            echo "This branch should be deleted $line\n";
            exec("git branch -d $line");
        }
        $k++;
    }
?>

0

Ecco una funzione che puoi aggiungere al tuo bash_profile per renderlo più semplice.

Utilizzo in un repository Git:

  • branch stampa tutte le filiali locali
  • branch -r stampa tutti i rami remoti

Funzione:

branch() {
   local pattern="s/^..//"
   local arg=""
   if [[ $@ == "-r" ]]; then
      pattern="s/^..(.*?)( ->.*)?$/\1/"
      arg=" -r "
      echo '-r provided'
   fi
   for k in $(git branch $arg | perl -pe "$pattern"); do
      echo -e $(git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1)\\t$k
   done | sort -r
}

0

In PowerShell, di seguito sono mostrate le filiali sul telecomando che sono già state unite e che hanno almeno due settimane (il author:relativeformato inizia a visualizzare settimane anziché giorni a due settimane):

$safeBranchRegex = "origin/(HEAD|master|develop)$";
$remoteMergedBranches = git branch --remote --merged | %{$_.trim()};
git for-each-ref --sort='authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/remotes | ?{$_ -match "(weeks|months|years) ago" -and $_ -notmatch "origin/(HEAD|master|qa/)"} | %{$_.substring($_.indexof("origin/"))} | ?{$_ -in $remoteMergedBranches}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.