Registro Git avanzato
Lo scopo di qualsiasi sistema di controllo delle versioni รจ registrare le modifiche al tuo codice. Questo ti dร la possibilitร di tornare alla cronologia del tuo progetto per vedere chi ha contribuito a cosa, capire dove sono stati introdotti i bug e annullare le modifiche problematiche. Ma avere tutta questa cronologia disponibile รจ inutile se non sai come navigare. ร qui che entra in gioco il comando git log.
A questo punto, dovresti giร conoscere il comando di base git log per la visualizzazione dei commit. Ma puoi modificare questo output passando molti parametri diversi a git log.
Le funzionalitร avanzate di git log possono essere suddivise in due categorie: formattazione della modalitร di visualizzazione di ogni commit e filtraggio dei commit inclusi nell'output. Insieme, queste due competenze ti danno il potere di tornare al tuo progetto e trovare tutte le informazioni di cui potresti aver bisogno.
Formattazione dell'output del registro
Innanzitutto, questo articolo esaminerร i molti modi in cui l'output di git log puรฒ essere formattato. La maggior parte di questi si presenta sotto forma di flag che consentono di richiedere piรน o meno informazioni da git log.
Se non ti piace il formato predefinito di git log, puoi usare la funzionalitร di aliasing di git config per creare una scorciatoia per una qualsiasi delle opzioni di formattazione discusse di seguito. Consulta Il comando git config per scoprire come configurare un alias.
Oneline
Il flag โoneline condensa ogni commit in un'unica riga. Per impostazione predefinita, mostra solo l'ID di commit e la prima riga del messaggio di commit. Il tuo tipico output di git log โoneline sarร simile al seguente:
0e25143 Merge branch 'feature'
ad8621a Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad Add the initial code baseQuesto รจ molto utile per avere una panoramica generica sul tuo progetto.
Decorazione
Spesso รจ utile sapere a quale branch o tag รจ associato ogni commit. Il flag โdecorate fa sรฌ che git log mostri tutti i riferimenti (ad esempio, branch, tag, ecc.) che puntano a ciascun commit.
Questo puรฒ essere combinato con altre opzioni di configurazione. Ad esempio, l'esecuzione di git log โoneline โdecorate formatterร la cronologia dei commit in questo modo:
0e25143 (HEAD, main) Merge branch 'feature'
ad8621a (feature) Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad (tag: v0.9) Add the initial code baseQuesto ti fa sapere che anche il primo commit รจ stato sottoposto a checkout (indicato con HEAD) e che รจ anche la punta del branchย principale. Un altro branch chiamato feature punta al secondo commit, e infine il quarto commit รจ etichettato come v0.9.
I branch, i tag, l'HEAD e la cronologia dei commit sono quasi tutte le informazioni contenute nel tuo repository Git, quindi questo ti offre una visione piรน completa della struttura logica del tuo repository.
Differenze
Il comando git log include molte opzioni per visualizzare le differenze relative a ogni commit. Due delle opzioni piรน comuni sono โstat e -p.
L'opzione โstat mostra il numero di inserimenti ed eliminazioni in ogni file modificato da ogni commit (si noti che la modifica di una riga รจ rappresentata da 1 inserimento e 1 eliminazione). Questo รจ utile quando desideri avere un breve riepilogo delle modifiche introdotte da ogni commit. Ad esempio, il seguente commit ha aggiunto 67 righe al file hello.py e rimosso 38 righe:
commit f2a238924e89ca1d4947662928218a06d39068c3
Author: John <john@example.com>
Date: Fri Jun 25 17:30:28 2014 -0500
Add a new feature
hello.py | 105 ++++++++++++++++++++++++-----------------
1 file changed, 67 insertion(+), 38 deletions(-)La quantitร di segni + e - accanto al nome del file mostra il numero relativo di modifiche apportate a ciascun file modificato dal commit. Questo ti dร un'idea di dove si possono trovare le modifiche per ogni commit.
Se vuoi vedere le modifiche effettive introdotte da ogni commit, puoi passare l'opzione -p a git log. Questo restituisce l'intera patch che rappresenta quel commit:
commit 16b36c697eb2d24302f89aa22d9170dfe609855b
Author: Mary <mary@example.com>
Date: Fri Jun 25 17:31:57 2014 -0500
Fix a bug in the feature
diff --git a/hello.py b/hello.py
index 18ca709..c673b40 100644
--- a/hello.py
+++ b/hello.py
@@ -13,14 +13,14 @@ B
-print("Hello, World!")
+print("Hello, Git!")Per i commit con molte modifiche, l'output risultante puรฒ diventare piuttosto lungo e ingombrante. Il piรน delle volte, se stai visualizzando una patch completa, probabilmente stai cercando una modifica specifica. Per questo, รจ utile usare l'opzione piccone.
Lo Shortlog
Il comando git shortlog รจ una versione speciale di git log destinata alla creazione di annunci di rilascio. Raggruppa ogni commit per autore e visualizza la prima riga di ogni messaggio di commit. Questo รจ un modo semplice per vedere chi sta lavorando su cosa.
Ad esempio, se due sviluppatori hanno contribuito con 5 commit a un progetto, l'output di git shortlog potrebbe essere il seguente:
Mary (2):
Fix a bug in the feature
Fix a serious security hole in our framework
John (3):
Add the initial code base
Add a new feature
Merge branch 'feature'Per impostazione predefinita, git shortlog ordina l'output in base al nome dell'autore, ma puoi anche passare l'opzione -n per ordinare in base al numero di commit per autore.
grafici
L'opzione โgraph disegna un grafico ASCII che rappresenta la struttura ramificata della cronologia dei commit. Questo รจ comunemente usato insieme ai comandi โoneline e โdecorate per rendere piรน facile vedere quale commit appartiene a quale branch:
git log --graph --oneline --decoratePer un semplice repository con solo 2 branch, il risultato sarร il seguente:
* 0e25143 (HEAD, main) Merge branch 'feature'
|\
| * 16b36c6 Fix a bug in the new feature
| * 23ad9ad Start a new feature
* | ad8621a Fix a critical security issue
|/
* 400e4b7 Fix typos in the documentation
* 160e224 Add the initial code baseL'asterisco mostra in quale branch si trovava il commit, quindi il grafico sopra indica che i commit 23ad9ad e 16b36c6 si trovano su un branch tematico e il resto sul branchย principale.
Sebbene questa sia una buona opzione per i repository semplici, probabilmente sarร piรน utile usare uno strumento di visualizzazione piรน completo come gitk o Sourcetreeย per progetti molto ramificati.
Formattazione personalizzata
Per tutte le altre tue esigenze di formattazione di git log, puoi usare l'opzione --pretty=format:"<string>". Questo ti consente di visualizzare ogni commit come preferisci utilizzando segnaposti in stile printf.
Ad esempio, i caratteri %cn, %h e %cd nel seguente comando sono sostituiti rispettivamente dal nome di chi ha eseguito il commit, dall'hash abbreviato del commit e dalla data dell'autore del commit.
git log --pretty=format:"%cn committed %h on %cd"Il risultato รจ il seguente formato per ogni commit:
John committed 400e4b7 on Fri Jun 24 12:30:04 2014 -0500 John committed 89ab2cf on Thu Jun 23 17:09:42 2014 -0500 Mary committed 180e223 on Wed Jun 22 17:21:19 2014 -0500 John committed f12ca28 on Wed Jun 22 13:50:31 2014 -0500L'elenco completo dei segnaposti รจ disponibile nella sezione Pretty Formats della pagina del manuale di git log.
Oltre a consentirti di visualizzare solo le informazioni che ti interessano, l'opzione --pretty=format:"<string>" รจ particolarmente utile quando stai cercando di reindirizzare l'output di git log a un altro comando.
Filtrare la cronologia dei commit
La formattazione del modo in cui ogni commit viene visualizzato รจ solo metร dell'impegno per imparare Git Log. L'altra metร รจ capire come navigare nella cronologia dei commit. Il resto di questo articolo introduce alcuni dei modi avanzati per selezionare commit specifici nella cronologia del progetto utilizzando git log. Tutti questi possono essere combinati con una qualsiasi delle opzioni di formattazione discusse sopra.
Per quantitร
L'opzione di filtro piรน semplice per git log รจ limitare il numero di commit visualizzati. Quando sei interessato solo agli ultimi commit, questo ti evita la fatica di visualizzare tutti i commit in una pagina.
Puoi limitare l'output di git log includendo l'opzione -<n>. Ad esempio, il comando seguente mostrerร solo i 3 commit piรน recenti.
git log -3Per data
Se stai cercando un commit per un periodo di tempo specifico, puoi utilizzare i contrassegni โafter o โbefore per filtrare i commit per data. Entrambi accettano una varietร di formati di data come parametri. Ad esempio, il comando seguente mostra solo i commit creati dopo il 1ยฐ luglio 2014 (incluso):
git log --after="2014-7-1"Puoi anche inserire riferimenti relativi come "1 settimana fa" e "ieri":
git log --after="yesterday"Per cercare un commit creato tra due date, puoi fornire sia una data โprima che una dopo. Ad esempio, per visualizzare tutti i commit aggiunti tra il 1 luglio 2014 e il 4 luglio 2014, userai quanto segue:
git log --after="2014-7-1" --before="2014-7-4"Per i commit con molte modifiche, l'output risultante puรฒ diventare piuttosto lungo e ingombrante. Il piรน delle volte, se stai visualizzando una patch completa, probabilmente stai cercando una modifica specifica. Per questo, รจ utile usare l'opzione piccone.
Per autore
Quando cerchi solo i commit creati da un determinato utente, usa il flag โauthor. Questa opzione accetta un'espressione regolare e restituisce tutti i commit il cui autore corrisponde a quel modello. Se sai esattamente chi stai cercando, puoi usare una semplice vecchia stringa invece di un'espressione regolare:
git log --author="John"Mostra tutti i commit il cui autore include il nome John. Il nome dell'autore non deve necessariamente corrispondere esattamente, deve solo contenere la frase specificata.
Puoi anche usare espressioni regolari per creare ricerche piรน complesse. Ad esempio, il comando seguente cerca i commit di Mary o John.
git log --author="John\|Mary"Nota che anche l'email dell'autore รจ inclusa con il nome dell'autore, quindi puoi usare questa opzione anche per cercare tramite email.
Se il tuo flusso di lavoro separa gli autori dei commit dagli autori, il flag โcommitter funziona nello stesso modo.
Per messaggio
Per filtrare i commit in base al messaggio di commit, usa il flag โgrep. Questo funziona proprio come il flag โauthor di cui si รจ parlato sopra, ma esegue la corrispondenza in base al messaggio di commit anzichรฉ all'autore.
Ad esempio, se il tuo team include i numeri dei problemi pertinenti in ogni messaggio di commit, puoi usare un'espressione come quella di seguito per estrarre tutti i commit relativi a quel problema:
git log --grep="JRA-224:"Puoi anche passare il parametro -i a git log per fare in modo che ignori le differenze tra maiuscole e minuscole durante la corrispondenza dei modelli.
Per file
Molte volte, ti interessano solo le modifiche apportate a un determinato file. Per mostrare la cronologia relativa a un file, tutto ciรฒ che devi fare รจ inserire il percorso del file. Ad esempio, l'espressione di seguito restituisce tutti i commit che hanno influito sul file foo.py o bar.py:
git log -- foo.py bar.pyIl parametro โ รจ usato per indicare a git log che gli argomenti successivi sono i percorsi dei file e non i nomi dei branch. Se non c'รจ alcuna possibilitร di confusione con un branch, puoi omettere il โ.
Per contenuto
ร anche possibile cercare commit che introducono o rimuovono una determinata riga di codice sorgente. Questo si chiama piccone e assume la forma di una -S"<string>". Ad esempio, se vuoi sapere quando รจ stata aggiunta la stringa Hello, World! a un file del progetto, devi usare il comando seguente:
git log -S"Hello, World!"Se vuoi effettuare una ricerca utilizzando un'espressione regolare anzichรฉ una stringa, puoi invece usare il flag -G"<regex>".
Questo รจ uno strumento di debug molto potente, in quanto consente di individuare tutti i commit che influiscono su una determinata riga di codice. Puรฒ anche mostrarti quando una riga รจ stata copiata o spostata in un altro file.
Per intervallo
Puoi passare una serie di commit a git log in modo da mostrare solo i commit contenuti in quell'intervallo. L'intervallo รจ specificato nel seguente formato, dove <since> e <until> sono riferimenti di commit:
git log <since>..<until>Questo comando รจ particolarmente utile quando si utilizzano riferimenti di branch come parametri. ร un modo semplice per mostrare le differenze tra 2 branch. Considera il seguente comando:
git log main..featureL'intervallo difunzionalitร ..principale contiene tutti i commit che si trovano nel branch delle funzionalitร , ma non nel branchย principale. In altre parole, si tratta dei progressi della funzionalitร da quando รจ stata disattivata dal principale. Puoi visualizzarlo come segue:
Nota che se cambi l'ordine dell'intervallo (funzionalitร ..principale), otterrai tutti i commit nella sezione principale, ma non nella funzionalitร . Se git log emette dei commit per entrambe le versioni, significa che la tua cronologia รจ diversa.
Filtraggio dei commit di fusione
Per impostazione predefinita, git log include i commit di fusione nell'output. Ma se il tuo team ha una politica di fusione continua (vale a dire che unisce le modifiche a monte in sezioni tematiche invece di ribasare il branch tematico sul branch upstream), avrai numerosi commit di fusione estranei nella cronologia del tuo progetto.
Puoi impedire a git log di visualizzare questi commit di fusione passando il flag โno-merges:
git log --no-mergesD'altra parte, se sei interessato solo ai commit di fusione, puoi usare il flag โmerges:
git log --mergesQuesto restituisce tutti i commit che hanno almeno due genitori.
Riepilogo
Ora dovresti sentirti abbastanza a tuo agio nell'usare i parametri avanzati di git log per formattare l'output e selezionare i commit che desideri visualizzare. Questo ti offre la possibilitร di ottenere esattamente ciรฒ di cui hai bisogno dalla cronologia del tuo progetto.
Queste nuove competenze sono una parte importante del tuo toolkit Git, ma ricorda che git log viene spesso usato insieme ad altri comandi Git. Una volta trovato il commit che stai cercando, di solito lo passi a git checkout, git revert o qualche altro strumento per manipolare la cronologia dei commit. Quindi, assicurati di continuare ad approfondire le funzionalitร avanzate di Git.