Che cos'è il tag git, come creare tag e come controllare i tag remoti git


524

quando controllo il tag git remoto uso il comando in questo modo:

git checkout -b local_branch_name origin/remote_tag_name

Ho ricevuto un errore del genere:

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

Posso trovare remote_tag_name quando uso il comando tag git.

Risposte:


1154

Cominciamo spiegando cos'è un tag in git

inserisci qui la descrizione dell'immagine

Un tag viene utilizzato per etichettare e contrassegnare un commit specifico nella cronologia.
Di solito viene utilizzato per contrassegnare i punti di rilascio (ad es. V1.0, ecc.).

Sebbene un tag possa apparire simile a un ramo , tuttavia, un tag non cambia . Indica direttamente un commit specifico nella cronologia.

inserisci qui la descrizione dell'immagine


Non sarai in grado di effettuare il checkout dei tag se non è localmente nel tuo repository, quindi per prima cosa devi inserire fetchi tag nel tuo repository locale.

Innanzitutto, 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

Quindi controlla il tag eseguendo

$ git checkout tags/<tag_name> -b <branch_name>

Invece di originusare il tags/prefisso.


In questo esempio hai 2 tag versione 1.0 e versione 1.1 puoi verificarli con uno dei seguenti:

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

Tutto quanto sopra farà lo stesso poiché il tag è solo un puntatore a un determinato commit.

inserisci qui la descrizione dell'immagine
origine: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Come visualizzare 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 tag?

Esistono 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 è possibile aggiungere metadati come in un commit git:
nome, e-mail, data, commento e firma

inserisci qui la descrizione dell'immagine

Come eliminare i tag?

# delete any (local) given tag
$ git tag -d <tag name>

# Delete a tag from the server with push tags
$ git push --delete origin <tag name>

Come clonare un tag specifico?

Per afferrare il contenuto di un determinato tag, puoi usare il checkoutcomando. Come spiegato sopra, i tag sono come qualsiasi altro commit, quindi possiamo usare checkoute invece di usare SHA-1 semplicemente sostituendolo 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/<tag> -b <branch>

Opzione 2:

Usando il comando clone

Poiché git supporta il clone shallow aggiungendo il --branchcomando clone, possiamo usare il nome del tag invece del nome del ramo. Git sa come "tradurre" il dato SHA-1 nel commit pertinente

# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

git clone --branch =

--branch può anche prendere tag e scollegare HEAD a quel commit nel repository risultante.


Come spingere i tag?

git push --tags

Per inviare tutti i tag:

# Push all tags
$ git push --tags 

Usando refs/tagsinvece di specificare semplicemente <tagname>.

Perché? - Si consiglia di utilizzare refs/tagspoiché a volte i tag possono avere lo stesso nome dei rami e il semplice git push spingerà il ramo invece del tag

Per inviare tag annotati e tag della catena della cronologia corrente utilizzare:

git push --follow-tags

Questo flag --follow-tagsspinge entrambi i commit e solo i tag che sono sia:

  • Tag con annotazioni (in modo da poter saltare tag di build locali / temporanei)
  • Tag raggiungibili (un antenato) dal ramo corrente (situato nella cronologia)

inserisci qui la descrizione dell'immagine

Da Git 2.4 puoi impostarlo usando la configurazione

$ git config --global push.followTags true

Cheatsheet: inserisci qui la descrizione dell'immagine



3
simpatico. git checkout A. che cos'è A? Come hai creato A?
Miele

3
@CodeWizard Bel diagramma di flusso! Quale software hai usato per produrlo?
Giovanni Lovato,

4
@Honey Aè un hash di commit
Alex Baklanov

2
@GiovanniLovato Il diagramma di flusso è di terze parti. Il link all'immagine è backlog.com/git-tutorial/img/post/stepup/… che proviene da questa pagina backlog.com/git-tutorial/stepup/stepup4_1.html del sito web chiamato Git Beginner's Guide for Dummies (backlog .com).
George,

2
Vale la pena notare che git checkout tags/<tag_name> -b <branch_name>richiede il -b <branch_name>. git checkout tags/<tag_name>mi ha dato una testa distaccata. Come da questo articolo sulla testa staccata , si evita una testa staccata creando e cancellando temporaneamente un ramo. Questo è piuttosto un flusso di lavoro alieno. Chiaramente, come utente git ho bisogno di abituarmi a creare ed eliminare filiali per divertimento e profitto.
icc97,

194

(Questa risposta ha impiegato un po 'di tempo a scrivere e la risposta di codeWizard è corretta per finalità ed essenza, ma non è del tutto completa, quindi pubblicherò comunque.)


Non esiste un "tag Git remoto". Ci sono solo "tag". Sottolineo tutto ciò non per essere pedante, 1 ma perché c'è molta confusione al riguardo con gli utenti Git casuali e la documentazione Git non è molto utile 2 per i principianti. (Non è chiaro se la confusione deriva dalla scarsa documentazione o dalla scarsa documentazione perché ciò è intrinsecamente un po 'confuso, o cosa.)

Ci sono "rami remote", più propriamente chiamati "remote-tracciamento rami", ma vale la pena notare che questi sono in realtà gli enti locali. Non ci sono tag remoti, però (a meno che tu non li reinventi). Esistono solo tag locali, quindi è necessario ottenere il tag localmente per poterlo utilizzare.

Il modulo generale per i nomi di commit specifici, che Git chiama riferimenti, è qualsiasi stringa che inizia con refs/. Una stringa che inizia con i refs/heads/nomi di un ramo; una stringa che inizia con i refs/remotes/nomi di un ramo di tracciamento remoto; e una stringa che inizia con i refs/tags/nomi di un tag. Il nome refs/stashè il riferimento stash (come usato da git stash; notare la mancanza di una barra finale).

Ci sono alcuni nomi speciali di casi insoliti che non iniziano con refs/: HEAD, ORIG_HEAD, MERGE_HEAD, e CHERRY_PICK_HEAD, in particolare, sono tutti anche nomi che possono fare riferimento a specifici commit (anche se HEADdi solito contiene il nome di un ramo, ad esempio, contiene ). Ma in generale, i riferimenti iniziano con .ref: refs/heads/branchrefs/

Una cosa che Git fa per rendere questo confuso è che ti permette di omettere refs/, e spesso la parola dopo refs/. Ad esempio, puoi omettere refs/heads/o refs/tags/quando ti riferisci a una filiale o tag locale, e infatti devi ometterti refs/heads/quando controlli una filiale 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: vale a dire durante fetche durante le pushoperazioni. Puoi anche usarli git ls-remoteo git remote showvederli, ma fetche pushsono i punti di contatto più interessanti.

Refspecs

Durante fetche push, Git usa stringhe che chiama refspecs per trasferire riferimenti tra il repository locale e remoto. Pertanto, è in questi momenti, e tramite refspecs, che due repository Git possono sincronizzarsi tra loro. Una volta che i tuoi nomi sono sincronizzati, puoi usare lo stesso nome usato da qualcuno con il telecomando. C'è un po 'di magia speciale qui fetch, e influenza sia i nomi dei rami che i nomi dei tag.

Dovresti pensare di git fetchindirizzare il tuo Git a richiamare (o forse a un messaggio di testo) un altro Git — il "remoto" —e avere una conversazione con esso. All'inizio di questa conversazione, il telecomando elenca tutti i suoi riferimenti: tutto dentro refs/heads/e tutto dentro refs/tags/, insieme a tutti gli altri riferimenti che ha. Git esegue la scansione di questi e (in base al solito refspec fetch) rinomina i loro rami.

Diamo un'occhiata al normale refspec per il telecomando chiamato origin:

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

Questo refspec indica a Git di prendere ogni corrispondenza del nome refs/heads/*—ie, ogni ramo sul telecomando — e cambiare il suo nome in refs/remotes/origin/*, cioè mantenere la parte abbinata uguale, cambiando il nome del ramo ( refs/heads/) in un nome di ramo di tracciamento remoto ( refs/remotes/, in particolare , refs/remotes/origin/).

È attraverso questo refspec che origini rami diventano i tuoi rami di localizzazione remota per remoto origin. Il nome del ramo diventa il nome del ramo di tracciamento remoto, con il nome del telecomando, in questo caso originincluso. Il segno più +nella parte anteriore di refspec imposta il flag "force", ovvero il ramo di tracciamento remoto verrà aggiornato in modo che corrisponda al nome del ramo del telecomando, indipendentemente da ciò che serve per farlo corrispondere. (Senza +, gli aggiornamenti di diramazione sono limitati alle modifiche "avanzamento rapido" e gli aggiornamenti dei tag sono semplicemente ignorati dalla versione 1.8.2 di Git o giù di lì, prima di applicare le stesse regole di avanzamento rapido.)

tag

E i tag? Non c'è refspec per loro, almeno non di default. Puoi impostarne uno, nel qual caso la forma del refspec dipende da te; oppure puoi correre git fetch --tags. L'utilizzo --tagsha l'effetto di aggiungere refs/tags/*:refs/tags/*a refspec, ovvero porta tutti i tag ( ma non aggiorna il tag se hai già un tag con quel nome, indipendentemente da ciò che dice il tag del telecomando Modifica, gennaio 2017: da Git 2.10 , i test mostrano che --tagsaggiorna forzatamente i tag dai tag del telecomando, come se refspec leggesse +refs/tags/*:refs/tags/*; questa potrebbe essere una differenza di comportamento rispetto a una versione precedente di Git).

Si noti che non è possibile rinominare qui: se remote originha tag xyzzy, e tu no, e tu git fetch origin "refs/tags/*:refs/tags/*", vieni refs/tags/xyzzyaggiunto al tuo repository (indicando lo stesso commit del telecomando). Se usi, il +refs/tags/*:refs/tags/*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 ottiene dal loro Git".

Tag automagic durante il recupero

Per motivi storici, 3 se non si utilizza né l' --tagsopzione né l' --no-tagsopzione, git fetchviene eseguita un'azione speciale. Ricorda che abbiamo detto sopra che il telecomando inizia visualizzando al tuo Git locale tutti i suoi riferimenti, indipendentemente dal fatto che il tuo Git locale voglia vederli o meno. 4 Il tuo Git prende nota di tutti i tag che vede a questo punto. Quindi, non appena inizia a scaricare qualsiasi oggetto commit necessario per gestire qualunque cosa stia recuperando, se uno di questi commit ha lo stesso ID di uno di quei tag, git aggiungerà quel tag - o quei tag, se più tag hanno quell'ID - a il tuo repository.

Modifica, gennaio 2017: il test mostra che il comportamento in Git 2.10 è ora: Se il loro Git fornisce un tag di nome T , e non si dispone di un tag di nome T , e il commit ID associato a T è un antenato di uno dei loro rami che git fetchstai esaminando, Git aggiunge T ai tuoi tag con o senza --tags. L'aggiunta --tagsfa sì che Git ottenga tutti i loro tag e imponga anche l'aggiornamento.

Linea di fondo

Potrebbe essere necessario utilizzare git fetch --tagsper ottenere i loro tag. Se i loro nomi dei tag sono in conflitto con i nomi dei tag esistenti, potrebbe essere necessario (a seconda della versione di Git) persino eliminare (o rinominare) alcuni dei tag e quindi eseguirli git fetch --tagsper ottenere i tag. Poiché i tag, a differenza dei rami remoti, non hanno una ridenominazione automatica, i nomi dei tag devono corrispondere ai nomi dei tag, motivo per cui si possono avere problemi con conflitti.

Nella maggior parte dei casi normali, tuttavia, un semplice git fetcheseguirà il lavoro, portando a termine i propri commit e i tag corrispondenti, e dal momento che, chiunque essi siano, taggeranno i commit nel momento in cui pubblicano tali commit, continuerai con i loro tag. Se non crei i tuoi tag, né mescoli il loro repository e altri repository (tramite più telecomandi), non avrai nemmeno collisioni di nomi di tag, quindi non dovrai preoccuparti di eliminare o rinominare i tag per ottenere i loro tag.

Quando hai bisogno di nomi qualificati

Ho già detto che è possibile omettere refs/quasi sempre, ed refs/heads/e refs/tags/e così via la maggior parte del tempo. Ma quando non puoi?

La (in ogni caso o quasi completa) risposta completa è la gitrevisionsdocumentazione . Git risolverà un nome in un ID commit usando la sequenza in sei passaggi indicata nel collegamento. Curiosamente, i tag sovrascrivono i rami: se c'è un tag xyzzye un ramo xyzzye puntano a commit diversi, allora:

git rev-parse xyzzy

ti darà l'ID a cui punta il tag. Tuttavia - e questo è ciò che manca gitrevisions- git checkoutpreferisce i nomi dei rami, quindi git checkout xyzzyti metterà sul ramo, ignorando il tag.

In caso di ambiguità, puoi quasi sempre sillabare il nome di riferimento usando il suo nome completo refs/heads/xyzzyo refs/tags/xyzzy. (Si noti che questo fa il lavoro con git checkout, ma in un modo forse inaspettato: git checkout refs/heads/xyzzyprovoca una cassa indipendente-testa, piuttosto che un checkout ramo Questo è il motivo per cui è sufficiente notare che. git checkoutUtilizzerà il nome breve come un nome di primo ramo: è così che si controlla il ramo xyzzyanche se xyzzyesiste il tag . Se vuoi controllare il tag, puoi usarlo refs/tags/xyzzy.)

Poiché (come gitrevisionsnote) Git proverà , puoi anche semplicemente scrivere per identificare il commit taggato . (Se qualcuno è riuscito a scrivere un riferimento valido nominato in , tuttavia, questo si risolverà come . Ma normalmente dovrebbero essere presenti solo i vari nomi .)refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


1 Va bene, va bene, "non solo per essere pedanti". :-)

2 Alcuni direbbero "molto inutile", e in realtà tenderei ad essere d'accordo.

3 Fondamentalmente, git fetche l'intero concetto di telecomandi e refspec, è stato un po 'in ritardo con Git, accadendo all'epoca di Git 1.5. Prima di allora c'erano solo alcuni casi speciali ad hoc, e il recupero dei tag era uno di questi, quindi è stato nonno tramite codice speciale.

4 Se aiuta, pensa a Git remoto come un lampeggiatore , nel significato gergale.


Ottimo commento. Un piccolo nit: git fetchprenderà solo i tag del telecomando dato l' --tagsarg.
circa

@cweekly: il comportamento dei --tags, --no-tagse di default è in realtà abbastanza difficile. L'impostazione predefinita è di inserire i tag che non hai nei commit che stai eseguendo. (Vedi la modifica di gennaio 2017.) Ma ci sono anche dei difetti qui, e Git moderno sta avendo i suoi --tags / --no-tags codice di gestione rivisto ancora una volta, il che probabilmente porterà a casi angolari ancora più speciali.
Torek,

1

Per estrarre un tag git, esegui il seguente comando

git checkout tags/tag-name -b branch-name

ad esempio, come indicato di seguito.

 git checkout tags/v1.0 -b v1.0-branch

Per recuperare tutti i tag utilizzare il comando

git fetch --all --tags

0

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

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.