Introduzione
Git supporta due tipi di tag: lightweight, che sono solo ref che puntano a commit, e annotated, che sono oggetti Git completi con metadati. Usa i tag annotated per le release.
Creare
git tag v1.0.0 # lightweight
git tag -a v1.0.0 -m "1.0 GA" # annotated
git tag -s v1.0.0 -m "Signed" # annotated firmato GPG
git tag -a v1.0.0 a1b2c3d -m "..." # tagga un commit specifico
Cosa memorizzano i tag annotated
git cat-file -t v1.0.0
# tag
git cat-file -p v1.0.0
# object <commit-sha>
# type commit
# tag v1.0.0
# tagger Ada <[email protected]> 1714300000 +0000
#
# 1.0 GA
Un tag annotated è un proprio oggetto. Ha il proprio SHA distinto dal commit a cui punta, un tagger e una data, un messaggio e una firma opzionale.
Cosa i tag lightweight non memorizzano
Un tag lightweight è solo refs/tags/v1.0.0 contenente uno SHA di commit. Non c'è messaggio, nessun tagger, nessuna firma. git describe, git tag -v e molti strumenti CI di rilascio assumono tag annotated e si comportano stranamente con quelli lightweight.
Ispezionare
git show v1.0.0
git tag -l --format='%(refname:short) %(objecttype) %(taggername) %(subject)'
I tag lightweight mostrano commit come tipo di oggetto; i tag annotated mostrano tag.
Firmare e verificare
git tag -s v1.0.0 -m "Signed"
git tag -v v1.0.0
# gpg: Good signature from "Ada Lovelace <[email protected]>"
La firma SSH è anche supportata in Git moderno:
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git tag -s v1.1.0 -m "SSH-signed"
Scegliere
- Usa annotated per le release, qualsiasi cosa pubblichi, qualsiasi cosa tu firmi.
- Usa lightweight per segnalibri locali ad hoc (es. "ricorda questo commit prima di fare rebase").
Pushare i tag
git push origin v1.0.0
git push origin --tags
git push --follow-tags # solo tag annotated raggiungibili dai commit pushati
--follow-tags ignora deliberatamente i tag lightweight, che è di solito ciò che vuoi.
Dereferenziamento dei tag
Molti comandi dereferenziano automaticamente un tag annotated al commit a cui punta; alcuni no. Usa ^{} per forzare il dereferenziamento negli script:
git rev-parse v1.0.0 # SHA dell'oggetto tag (annotated)
git rev-parse v1.0.0^{} # SHA del commit a cui punta
git rev-parse v1.0.0^{commit} # uguale, con asserzione di tipo
git for-each-ref --format='%(refname:short) %(*objectname)' refs/tags
Il segnaposto %(*objectname) dà il commit dereferenziato per i tag ed è vuoto per i ref non-tag. Questo pattern è essenziale per gli script di rilascio che hanno bisogno di uno SHA di commit da un nome di tag.
Errori comuni
Taggare le release con un semplice git tag v1.0 e perdere tagger/data/messaggio nei log di audit. Passa sempre -a o -s. Spostare un tag pubblicato a un nuovo commit ("force-tag"); gli utenti a valle hanno già cachato il vecchio SHA e potrebbero non recepire il cambiamento. Emetti invece v1.0.1. Usare tag lightweight come segnalibri nominati condivisi tra un team; se devi condividere, preferisci branch o tag annotated. Infine, aspettarsi che git describe funzioni senza tag annotated; per default conta solo quelli annotated (--tags opta in per i lightweight, con avvertenze).