Cos'è git tag, come creare tag & come fare il checkout dei tag remoti di git

quando faccio il checkout del tag git remoto uso un comando come questo:

git checkout -b local_branch_name origin/remote_tag_name

Ho ottenuto un errore come questo:

error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.

Posso trovare remote_tag_name quando uso il comando git tag.

Soluzione

Cominciamo a spiegare cos'è un tag in git

Un tag è usato per etichettare e contrassegnare uno specifico commit nella storia.
Di solito è usato per contrassegnare i punti di rilascio (es. v1.0, ecc.).

Sebbene un tag possa apparire simile ad un ramo, un tag, tuttavia, non cambia.
Punta direttamente ad un specifico commit nella storia.


Non sarai in grado di fare il checkout dei tag se non è localmente nel tuo repository, quindi prima devi "recuperare" i tag nel tuo repository locale.

Prima di tutto, assicurati che il tag esista localmente facendo

# --all will fetch all the remotes.
# --tags will fetch all tags as well
git fetch --all --tags --prune

Poi controlla il tag eseguendo

git checkout tags/ -b 

Invece di origin usa il prefisso tags/.


In questo esempio hai 2 tag versione 1.0 & versione 1.1 puoi controllarli con uno dei seguenti:

git checkout A  ...
git checkout version 1.0  ...
git checkout tags/version 1.0  ...

Tutti i precedenti faranno lo stesso, poiché il tag è solo un puntatore a un dato commit.

origine: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Come vedere l'elenco di tutti i tag?

# list all tags
git tag

# list all tags with given pattern ex: v-
git tag --list 'v-*'

Come creare i tag?

Ci sono 2 modi per creare un tag:

# lightweight tag 
git tag 

# annotated tag
git tag -a

La differenza tra i 2 è che quando si crea un tag annotato si possono aggiungere metadati come in un commit git:
nome, e-mail, data, commento & firma

Come cancellare i tag?

# delete any given tag
git tag -d 

# Don't forget to remove the deleted tag form the server with push tags

Come clonare un tag specifico?

Per prendere il contenuto di un dato tag puoi usare il comando checkout.
Come spiegato sopra i tag sono come qualsiasi altro commit, quindi possiamo usare checkout e invece di usare lo SHA-1 sostituirlo semplicemente con tag_name

Opzione 1:

# Update the local git repo with the latest tags from all remotes
git fetch --all

# checkout the specific tag
git checkout tags/ -b 

Opzione 2:

Usando il comando clone

Dato che git supporta shallow clone aggiungendo il --branch al comando clone possiamo usare il nome del tag invece del nome del ramo. Git sa come "tradurre" lo SHA-1 dato al relativo commit

# Clone a specific tag name using git clone 
 git clone  --branch=

git clone --branch=

--branch può anche prendere i tag e stacca l'HEAD a quel commit nel repository risultante.


Come spingere i tag?

`git push --tags

Per spingere tutti i tag:

git push --tags 

Per spingere i tag annotati e i tag della catena della storia corrente usa::

`git push --follow-tags

Questo flag --follow-tags spinge sia i commits che i soli tag che sono entrambi:

  • Tag annotati (in modo da poter saltare i tag locali/temp build)
  • Tag raggiungibili (un antenato) dal ramo corrente (situato nella cronologia)

Da Git 2.4 puoi impostarlo usando la configurazione

git config --global push.followTags true

Commentari (8)

(Questa risposta ha richiesto un po' di tempo per essere scritta, e la risposta di codeWizard's è corretta nello scopo e nell'essenza, ma non del tutto completa, quindi la posterò comunque).

Non esiste un "tag Git remoto". Ci sono solo "tag". Faccio notare tutto questo non per essere pedante,1 ma perché c'è molta confusione su questo con gli utenti occasionali di Git, e la documentazione di Git non è molto utile2 ai principianti. (Non è chiaro se la confusione viene a causa della scarsa documentazione, o la scarsa documentazione viene perché questo è intrinsecamente un po' confuso, o cosa). Ci sono "rami remoti", più propriamente chiamati "rami di tracciamento remoto", ma vale la pena notare che questi sono in realtà entità locali. Non ci sono tag remoti, però (a meno che non li si (ri)inventi). Ci sono solo tag locali, quindi è necessario ottenere il tag localmente per poterlo utilizzare. La forma generale per i nomi per specifici commit - che Git chiama references - è una qualsiasi stringa che inizia con refs/. Una stringa che inizia con refs/heads/ nomina un ramo; una stringa che inizia con refs/remotes/ nomina un ramo con tracciamento remoto; e una stringa che inizia con refs/tags/ nomina un tag. Il nome refs/stash è il riferimento allo stash (come usato da git stash; nota la mancanza di una barra finale). Ci sono alcuni nomi speciali insoliti che non iniziano con refs/: HEAD, ORIG_HEAD, MERGE_HEAD, e CHERRY_PICK_HEAD in particolare sono tutti nomi che possono riferirsi a specifici commit (anche se HEAD normalmente contiene il nome di un ramo, cioè contiene ref: refs/heads/branch). Ma in generale, i riferimenti iniziano con refs/. Una cosa che Git fa per rendere questo confuso è che ti permette di omettere il refs/, e spesso la parola dopo il refs/. Per esempio, puoi omettere refs/heads/ o refs/tags/ quando ti riferisci ad un ramo locale o ad un tag - e infatti devi omettere refs/heads/ quando fai il check-out di un ramo locale! Puoi farlo ogni volta che il risultato non è ambiguo, o - come abbiamo appena notato - quando devi farlo (per git checkout branch). È vero che i riferimenti esistono non solo nel proprio repository, ma anche in repository remoti. Tuttavia, Git ti dà accesso ai riferimenti di un repository remoto solo in momenti molto specifici: cioè, durante le operazioni di fetch e push. Puoi anche usare git ls-remote o git remote show per vederli, ma fetch e push sono i punti di contatto più interessanti.

Refspecs

Durante il fetch e il push, Git usa delle stringhe che chiama refspecs per trasferire i riferimenti tra il repository locale e quello remoto. Quindi, è in questi momenti, e attraverso le refspecs, che due repository Git possono essere sincronizzati tra loro. Una volta che i vostri nomi sono sincronizzati, potete usare lo stesso nome che qualcuno con il remoto usa. C'è qualche magia speciale qui su fetch, però, e riguarda sia i nomi dei rami che i nomi dei tag. Dovresti pensare a git fetch come se dirigessi il tuo Git a richiamare (o forse a mandare un messaggio di testo) un altro Git-il "remote"-e avere una conversazione con esso. All'inizio di questa conversazione, il remoto elenca tutti i suoi riferimenti: tutto in refs/heads/ e tutto in refs/tags/, insieme a qualsiasi altro riferimento che ha. Il tuo Git fa una scansione di questi e (basandosi sulla solita fetch refspec) rinomina i loro rami. Diamo un'occhiata al normale refspec per il remoto chiamato origin:

$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$ 

Questo refspec istruisce il tuo Git a prendere ogni nome che corrisponde a refs/heads/* - cioè, ogni ramo sul remoto - e cambiare il suo nome in refs/remotes/origin/*, cioè, mantenere la parte corrispondente allo stesso, cambiando il nome del ramo (refs/heads/) in un nome di ramo che traccia il remoto (refs/remotes/, in particolare, refs/remotes/origin/). È attraverso questo refspec che i rami di origin'diventano i tuoi rami di tracciamento remoto per il remoto origin. Il nome del ramo diventa il nome del ramo di tracciamento remoto, con il nome del remoto, in questo caso origin, incluso. Il segno più + davanti al refspec imposta il flag "force", cioè, il tuo ramo di remote-tracking sarà aggiornato per corrispondere al nome del ramo remoto, indipendentemente da ciò che serve per farlo corrispondere. (Senza il +, gli aggiornamenti del ramo sono limitati alle modifiche "fast forward" e gli aggiornamenti dei tag sono semplicemente ignorati dalla versione 1.8.2 di Git o giù di lì - prima di allora si applicavano le stesse regole di fast-forward).

Tag

Ma che dire dei tag? Non c'è un refspec per loro, almeno non di default. Puoi impostarne uno, nel qual caso la forma del refspec dipende da te; oppure puoi eseguire git fetch --tags. Usare --tags ha l'effetto di aggiungere refs/tags/*:refs/tags/* al refspec, cioè, porta sopra tutti i tag (ma non aggiorna il tuo tag se hai già un tag con quel nome, a prescindere da ciò che dice il tag del remoto' Edit, Jan 2017: a partire da Git 2.10, i test mostrano che --tags aggiorna forzatamente i tuoi tag dai tag remoti, come se la refspec leggesse +refs/tags/*:refs/tags/*; questa potrebbe essere una differenza di comportamento da una versione precedente di Git). Nota che non c'è nessuna ridenominazione qui: se il remoto origin ha il tag xyzzy, e tu no, e tu git fetch origin "refs/tags/*:refs/tags/*", avrai refs/tags/xyzzy aggiunto al tuo repository (che punta allo stesso commit del remoto). Se usi +refs/tags/*:refs/tags/* allora il tuo tag xyzzy, se ne hai uno, viene sostituito da quello di origin. Cioè, il flag di forza + su un refspec significa "sostituisci il valore del mio riferimento'con quello che il mio Git riceve dal loro Git".

Tag automatici durante il fetch

Per ragioni storiche,3 se non usi né l'opzione --tags né l'opzione --no-tags, git fetch compie azioni speciali. Ricorda che abbiamo detto sopra che il remoto inizia mostrando al tuo Git locale tutti i suoi riferimenti, che il tuo Git locale voglia vederli o meno.4 Il tuo Git prende nota di tutti i tag che vede a questo punto. Poi, mentre inizia a scaricare qualsiasi oggetto commit di cui ha bisogno per gestire qualsiasi cosa stia recuperando, se uno di quei commit ha lo stesso ID di uno di quei tag, git aggiungerà quel tag - o quei tag, se più tag hanno quell'ID - al tuo repository; Modifica, gennaio 2017: i test mostrano che il comportamento in Git 2.10 è ora: Se il loro Git fornisce un tag chiamato T, e tu non hai un tag chiamato T, e l'ID di commit associato a T è un antenato di uno dei loro rami che il tuo git fetch sta esaminando, il tuo Git aggiunge T ai tuoi tag con o senza --tags. L'aggiunta di --tags fa sì che il tuo Git ottenga tutti i loro tag, e forzi l'aggiornamento.

Linea di fondo

Potresti dover usare git fetch --tags per ottenere i loro tag. Se i loro nomi di tag sono in conflitto con i tuoi nomi di tag esistenti, potresti (a seconda della versione di Git) anche dover cancellare (o rinominare) alcuni dei tuoi tag, e poi eseguire git fetch --tags, per ottenere i loro tag. Poiché i tag - a differenza dei rami remoti - non hanno una ridenominazione automatica, i tuoi nomi di tag devono corrispondere ai loro nomi di tag, ed è per questo che puoi avere problemi di conflitti. Nella maggior parte dei casi normali, comunque, un semplice git fetch farà il lavoro, portando i loro commit e i loro tag corrispondenti, e poiché loro - chiunque essi siano - etichetteranno i commit nel momento in cui li pubblicano, tu sarai al passo con i loro tag. Se non crei i tuoi propri tag, né mischi i loro repository con altri repository (tramite telecomandi multipli), non avrai nemmeno collisioni di nomi di tag, quindi non dovrai preoccuparti di cancellare o rinominare i tag per ottenere i loro tag.

Quando hai bisogno di nomi qualificati

Ho detto sopra che puoi omettere refs/ quasi sempre, e refs/heads/ e refs/tags/ e così via la maggior parte delle volte. Ma quando non si può? La risposta completa (o quasi) è nella documentazione di gitrevisions. Git risolverà un nome in un ID di commit usando la sequenza di sei passi data nel link. Curiosamente, i tag sovrascrivono i rami: se c'è un tag xyzzy e un ramo xyzzy, e puntano a commit diversi, allora:

git rev-parse xyzzy

ti darà l'ID a cui punta il tag. Tuttavia - e questo è ciò che manca a gitrevisions - git checkout preferisce i nomi dei rami, quindi git checkout xyzzy ti metterà sul ramo, ignorando il tag. In caso di ambiguità, puoi quasi sempre scrivere il nome del ref usando il suo nome completo, refs/heads/xyzzy o refs/tags/xyzzy. (Nota che questo funziona con git checkout, ma in un modo forse inaspettato: git checkout refs/heads/xyzzy provoca un checkout detached-HEAD piuttosto che un checkout del ramo. Questo è il motivo per cui devi solo notare che git checkout userà prima il nome breve come nome del ramo: è così che si fa il checkout del ramo xyzzy anche se il tag xyzzy esiste. Se vuoi fare il checkout del tag, puoi usare refs/tags/xyzzy). Poiché (come nota gitrevisions) Git proverà refs/name, puoi anche semplicemente scrivere tags/xyzzy per identificare il commit con tag xyzzy. (Se qualcuno è riuscito a scrivere un riferimento valido chiamato xyzzy in $GIT_DIR, tuttavia, questo si risolverà come $GIT_DIR/xyzzy. Ma normalmente solo i vari nomi *HEAD dovrebbero essere in $GIT_DIR).

11Ok, ok, "non solo per essere pedante". :-) 22Alcuni direbbero "molto poco utile", e tenderei ad essere d'accordo, in effetti. Fondamentalmente, git fetch, e l'intero concetto di remote e refspecs, è stato un po' un'aggiunta tardiva a Git, avvenuta intorno al tempo di Git 1.5. Prima di allora c'erano solo alcuni casi speciali ad-hoc, e il tag-fetching era uno di questi, quindi è stato introdotto tramite codice speciale. 44Se aiuta, pensa al Git remoto come ad un flasher, nel significato gergale.

Commentari (2)

Per ottenere il codice specifico del tag prova a creare un nuovo ramo e aggiungi il codice del tag in esso. L'ho fatto con il comando: $git checkout -b newBranchName tagName.

Commentari (0)