Full Stack

Come usare i tag in Git

Autore

Manuel Ricci

Taggare è un’attività che in Git viene fatta soprattutto per indicare una versione di rilascio (es. 1.0.0).

Git supporta i tag, come anche altre VCS, e in sostanza si tratta di mettere un’etichetta ad uno specifico punto nella cronologia.

In Git un tag è una referenza a questo punto e possiamo immaginare un tag come una branch, ma che dopo la sua creazione non ha più una storia.

Come creare un tag in Git

Per creare un tag in git ci si può avvalere di due tipi di tag: lightweight e annotated.

Quello più semplice è, come avrete già supposto, il lightweight. Per crearne uno basta eseguire il comando

1$ git tag 1.0.0

Dove 1.0.0 è un valore arbitrario e può essere quello che desiderate, ma senza spazi. I tag lightweight sono come una branch che non cambia, sono solamente un puntatore ad una specifica commit.

L’altra tipologia, annotated o annotata, è un pochino più ricca. Per creare un tag annotato bisogna eseguire il comando:

1$ git tag -a 1.0.0 -m “la mia prima release”

I tag annotati Git li memorizza come oggetti nel database. Possiedono un checksum, hanno il nome di chi ha creato il tag, email, data di creazione e hanno un messaggio.

La raccomandazione è quella di usare i tag annotati per le cose importanti, mentre se non c’è bisogno di tutte queste info è meglio usare un tag lightweight.

I tag nella git directory

Ormai possiamo definirci degli habitué della git directory, facciamoci un salto per vedere cosa contiene un tag. La loro posizione è nella cartella .git/refs/tags

Facendo un ls vedremo tutti i tag che sono stati creati

1drwxrwxrwx 1 manuel manuel 4096 Jul  9  2023 .
2drwxrwxrwx 1 manuel manuel 4096 Jul  9 14:07 ..
3-rwxrwxrwx 1 manuel manuel   41 Jul  9  2023 tag-senza-spazi
4-rwxrwxrwx 1 manuel manuel   41 Jul  9 20:03 v0.2.0
5-rwxrwxrwx 1 manuel manuel   41 Jul  9 20:02 v0.2.1
6-rwxrwxrwx 1 manuel manuel   41 Jul  9 19:58 v1.0.0
7-rwxrwxrwx 1 manuel manuel   41 Jul  9 20:01 v1.0.1

Prendiamo in considerazione il tag tag-senza-spazi e 0.2.1 che rispettivamente sono un tag lightweight e un tag annotato (lo so perché li ho creati).

Se spiamo il contenuto del file tag-senza-spazi con cat troveremo un hash, il quale potrà essere usato con cat-file (il comando di git) per vedere a cosa fa riferimento.

1$ cat refs/tags/tag-senza-spazi
2$ 0f773b57245c9e0cdde37da0dbcf90e5b35755e5
3$ git cat-file -p 0f773b57245c9e0cdde37da0dbcf90e5b35755e5
4$ tree 96d0c8bf76753ee777c58ecc72563e7601f5a426
5   author Manuel Ricci <manuel@webtea.it> 1688904426 +0200
6   committer Manuel Ricci <manuel@webtea.it> 1688904426 +0200

La directory (il tree) a sua volta, sappiamo già dalla lezione sull’esplorazione della git directory che conterrà i file oggetto del tag e qui non si fa eccezione.

Per quanto riguarda invece il tag 0.2.1 vediamo cosa cambia:

1$ cat refs/tags/v0.2.1
2$ bc593eeaee111a8bf62711ed2427c1ac862ee575
3$ git cat-file -p bc593eeaee111a8bf62711ed2427c1ac862ee575
4$ object 0f773b57245c9e0cdde37da0dbcf90e5b35755e5
5   type commit
6   tag v0.2.1
7   tagger Manuel Ricci <manuel@webtea.it> 1688924221 +0200
8
9   test tag 2

In questo caso vediamo informazioni completamente diverse relative principalmente al tag, per vedere le informazioni viste con quello lightweight dobbiamo fare un cat-file dell’hash di object 0f773b…. Ciò che si potrà osservare sarà:

1tree 96d0c8bf76753ee777c58ecc72563e7601f5a426
2author Manuel Ricci <manuel@webtea.it> 1688904426 +0200
3committer Manuel Ricci <manuel@webtea.it> 1688904426 +0200
4
5Add message

Elencare i tag

Per elencare i tag presenti nella repo si può eseguire il comando:

1$ git tag

Se i tag sono tanti e si vogliono individuare quelli con uno specifico pattern e di conseguenza affinare la ricerca è possibile usare il flag --list o -l seguita da una wild card:

1$ git tag -l *-alpha

Questo comando una volta eseguito elencherà tutti i tag che hanno -alpha alla fine del nome.

Taggare una vecchia commit

Può succedere di dimenticare di taggare una vecchia commit, ma fortunatamente il comando git tag ci permette di taggare una vecchia versione, come? Usando l’hash ovviamente.

Di default git tag tagga implicitamente la commit alla quale HEAD fa riferimento. Per taggare una vecchia commit dobbiamo avvalerci di git log per trovare innanzitutto l’hash. Una volta trovato possiamo eseguire il comando:

1$ git tag -a v1.0.0 <SHA>

Se osserviamo il log dopo aver eseguito il comando precedente possiamo notare che il decoratore di quella commit si è arricchito della dicitura `tag: v1.0.0

Sostituire un vecchio tag

Ipotizziamo di aver sbagliato a taggare una commit e di voler usare il medesimo tag v0.2.0 con una nuova commit. Se provassimo semplicemente a utilizzare nuovamente il tag già creato, git risponderebbe:

1fatal: tag 'v0.2.0' already exists

Che possiamo tradurre con il tag è già in uso.

Per forzare lo spostamento del tag possiamo usare il flag -f che sta per FORCE. In questo modo:

1$ git tag -a -f v0.2.0 <SHA>

In questo modo il tag v0.2.0 verrà spostato alla nuova commit sovrascrivendo il precedente contenuto del tag.

Vedere lo stato della repo ad uno specifico tag

Nelle lezioni precedenti abbiamo usato checkout per vedere lo stato della nostra repo ad una specifica commit. Anche in questo caso possiamo usare git checkout per vedere lo stato della repo con quello specifico tag. Questo metterà la repo, come già sappiamo, in stato detached HEAD.

Cancellare un tag

Infine non ci rimane che cancellare i tag con il flag -d, in questo modo:

1$ git tag -d v1.0.0

Semplice, come bere un bicchiere d’acqua, ma del resto l'eliminazione è sempre così.

Prima di passare alla conclusione vorrei spendere ancora qualche parola sul versionamento.

Come versionare

Come avrete potuto notare uso uno specifico formato di versionamento. Come praticamente tutto, anche per il versionamento ci sono diverse metodologie, scuole di pensiero, credi, fedi e chi più ne ha più ne metta.

Personalmente uso semver o versionamento semantico, il quale sostanzialmente consiste nell’usare 3 numeri (es. 1.0.0, 0.2.0, ecc.) per indicare la versione del lavoro.

Quei tre numeri stanno per: MAJOR.MINOR.PATCH; che nello specifico significano: MAJOR: quando la codebase viene modificata in modo non retrocompatibile MINOR: quando vengono aggiunte funzionalità retrocompatibili PATCH: quando vengono corretti i bug in modo retrocompatibile

A questi numeri possono essere fatte seguire delle etichette aggiuntive per il pre-release e i metadati di build, come ad esempio: -alpha -beta -rc (release candidate)

Perché usare il semantic versioning?

Qui prendo spunto dal manifesto presente su semver.org. Il semantic versioning non è niente di rivoluzionario, si tratta di conformità, affinché i numeri di versione siano effettivamente utili.

Il problema che risolve è sostanzialmente quello di rendere l’inferno delle dipendenze un ricordo. Cosa che è vera fino ad un certo punto.

Se una dipendenza di un vostro progetto al momento dell’implementazione è alla versione 3.1.0 potete aggiornare il vostro progetto fintanto che la dipendenza ha una versione uguale o superiore alla 3.1.0, ma inferiore alle 4.0.0.

La realtà dei fatti è che dobbiamo sempre rimanere vigili e verificare che l’aggiornamento della dipendenza non spacchi tutto quello che abbiamo fatto.

Conclusioni

Archiviati anche i tag possiamo andare oltre e parlare di come rimuovere le modifiche ad un file.

Caricamento...

Diventiamo amici di penna? ✒️

Iscriviti alla newsletter per ricevere una mail ogni paio di settimane con le ultime novità, gli ultimi approfondimenti e gli ultimi corsi gratuiti puubblicati. Ogni tanto potrei scrivere qualcosa di commerciale, ma solo se mi autorizzi, altrimenti non ti disturberò oltre.

Se non ti piace la newsletter ti ricordo la community su Discord, dove puoi chiedere aiuto, fare domande e condividere le tue esperienze (ma soprattutto scambiare due meme con me). Ti aspetto!

Ho in previsione di mandarti una newsletter ogni due settimane e una commerciale quando capita.