Qu'est-ce que la balise git, comment créer des balises et comment extraire les balises git distantes

524

quand je vérifie la commande d'utilisation de balise git à distance comme ceci:

git checkout -b local_branch_name origin/remote_tag_name

J'ai une erreur comme celle-ci:

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

Je peux trouver remote_tag_name lorsque j'utilise la commande git tag.

Ryanqy
la source

Réponses:

1154

Commençons par expliquer ce qu'est un tag dans git

entrez la description de l'image ici

Une balise est utilisée pour étiqueter et marquer un commit spécifique dans l'historique.
Il est généralement utilisé pour marquer les points de sortie (par exemple, v1.0, etc.).

Bien qu'une balise puisse sembler similaire à une branche, une balise, cependant, ne change pas . Il pointe directement vers un commit spécifique dans l'historique.

entrez la description de l'image ici


Vous ne pourrez pas extraire les balises si elles ne sont pas localement dans votre référentiel, vous devez donc d'abord fetchles balises dans votre référentiel local.

Tout d'abord, assurez-vous que la balise existe localement en faisant

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

Vérifiez ensuite la balise en exécutant

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

Au lieu d' originutiliser le tags/préfixe.


Dans cet exemple, vous avez 2 balises version 1.0 et version 1.1, vous pouvez les vérifier avec l'une des options suivantes:

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

Tout ce qui précède fera de même puisque la balise n'est qu'un pointeur vers une validation donnée.

entrez la description de l'image ici
origine: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Comment voir la liste de toutes les balises?

# list all tags
$ git tag

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

Comment créer des tags?

Il existe 2 façons de créer une balise:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

La différence entre les 2 est que lors de la création d'une balise annotée, vous pouvez ajouter des métadonnées comme vous l'avez fait dans un commit git:
nom, e-mail, date, commentaire et signature

entrez la description de l'image ici

Comment supprimer des tags?

# 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>

Comment cloner une balise spécifique?

Afin de saisir le contenu d'une balise donnée, vous pouvez utiliser la checkoutcommande. Comme expliqué ci-dessus, les balises sont comme tout autre commit, nous pouvons donc utiliser checkoutet au lieu d'utiliser le SHA-1 le remplacer simplement par le tag_name

Option 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>

Option 2:

Utilisation de la commande clone

Puisque git prend en charge le clone superficiel en ajoutant la --branchà la commande clone, nous pouvons utiliser le nom de la balise au lieu du nom de la branche. Git sait comment "traduire" le SHA-1 donné en commit approprié

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

git clone --branch =

--branch peut également prendre des balises et détacher le HEAD lors de cette validation dans le référentiel résultant.


Comment pousser les tags?

git push --tags

Pour pousser toutes les balises:

# Push all tags
$ git push --tags 

Utiliser le refs/tagsau lieu de simplement spécifier le <tagname>.

Pourquoi? - Il est recommandé d'utiliser refs/tagscar parfois les balises peuvent avoir le même nom que vos branches et une simple poussée git poussera la branche au lieu de la balise

Pour envoyer des balises annotées et des balises de chaîne d'historique actuelles, utilisez:

git push --follow-tags

Cet indicateur --follow-tagspousse à la fois les validations et uniquement les balises qui sont à la fois:

  • Balises annotées (vous pouvez donc ignorer les balises de construction locales / temporaires)
  • Balises accessibles (un ancêtre) de la branche actuelle (située sur l'historique)

entrez la description de l'image ici

Depuis Git 2.4, vous pouvez le configurer en utilisant la configuration

$ git config --global push.followTags true

Cheatsheet: entrez la description de l'image ici


CodeWizard
la source
3
agréable. git checkout A. c'est quoi A? Comment avez-vous créé A?
Honey
3
@CodeWizard Joli organigramme! Quel logiciel avez-vous utilisé pour le produire?
Giovanni Lovato
4
@Honey Aest un hachage de validation
Alex Baklanov
2
@GiovanniLovato L'organigramme est un diagramme tiers. Le lien vers l'image est backlog.com/git-tutorial/img/post/stepup/… qui provient de cette page backlog.com/git-tutorial/stepup/stepup4_1.html du site Web appelé Git Beginner's Guide for Dummies (backlog .com).
George
2
Il convient de noter que git checkout tags/<tag_name> -b <branch_name>cela nécessite le -b <branch_name>. git checkout tags/<tag_name>m'a donné une tête détachée. Conformément à cet article sur la tête détachée , vous évitez une tête détachée en créant et en supprimant temporairement une branche. C'est un flux de travail assez étranger. De toute évidence, en tant qu'utilisateur git, je dois m'habituer à créer et supprimer des branches pour le plaisir et le profit.
icc97
194

(Cette réponse a pris du temps à écrire, et la réponse de codeWizard est correcte dans son objectif et son essence, mais pas entièrement complète, donc je posterai tout de même.)


Il n'existe pas de "balise Git distante". Il n'y a que des "tags". Je signale tout cela ne pas être pédant, 1 mais parce qu'il ya beaucoup de confusion à ce sujet avec les utilisateurs occasionnels Git, ainsi que la documentation Git est pas très utile 2 pour les débutants. (Il n'est pas clair si la confusion vient d'une mauvaise documentation, ou si la mauvaise documentation vient parce que c'est intrinsèquement quelque peu déroutant, ou quoi.)

Il existe des "succursales distantes", plus précisément appelées "succursales de suivi à distance", mais il convient de noter qu'il s'agit en fait d'entités locales. Il n'y a cependant pas de balises distantes (sauf si vous les (ré) inventez). Il n'y a que des balises locales, vous devez donc obtenir la balise localement pour l'utiliser.

La forme générale des noms pour les validations spécifiques - que Git appelle références - est n'importe quelle chaîne commençant par refs/. Une chaîne qui commence par refs/heads/nomme une branche; une chaîne commençant par les refs/remotes/noms d'une branche de suivi à distance; et une chaîne commençant par refs/tags/nomme une balise. Le nom refs/stashest la référence cachée (tel qu'utilisé par git stash; notez l'absence d'une barre oblique de fin).

Il y a des noms inhabituels de cas de spécial qui ne commencent pas avec refs/: HEAD, ORIG_HEAD, MERGE_HEAD, et CHERRY_PICK_HEADen particulier sont aussi des noms qui peuvent se référer à commits spécifiques (bien que HEADcontient normalement le nom d'une branche, à savoir, contient ). Mais en général, les références commencent par .ref: refs/heads/branchrefs/

Une chose que Git fait pour rendre cela déroutant, c'est qu'il vous permet d'omettre le refs/, et souvent le mot après refs/. Par exemple, vous pouvez omettre refs/heads/ou refs/tags/lorsque vous faites référence à une branche ou une balise locale - et en fait, vous devez l' omettre refs/heads/lors de la vérification d'une branche locale! Vous pouvez le faire chaque fois que le résultat est sans ambiguïté ou, comme nous venons de le noter, lorsque vous devez le faire (pour ).git checkout branch

Il est vrai que les références existent non seulement dans votre propre référentiel, mais également dans des référentiels distants. Cependant, Git vous donne accès aux références d'un référentiel distant uniquement à des moments très précis: à savoir pendant fetchet pendant les pushopérations. Vous pouvez également utiliser git ls-remoteou git remote showpour les voir, mais fetchet pushsont les points de contact les plus intéressants.

Refspecs

Pendant fetchet push, Git utilise des chaînes qu'il appelle refspecs pour transférer des références entre le référentiel local et distant. Ainsi, c'est à ces moments, et via les refspecs, que deux référentiels Git peuvent se synchroniser. Une fois vos noms synchronisés, vous pouvez utiliser le même nom que celui qui utilise la télécommande. Il y a cependant une magie spéciale ici fetch, et elle affecte à la fois les noms de branche et les noms de balise.

Vous devriez penser git fetchà demander à votre Git d'appeler (ou peut-être un SMS) un autre Git - le "distant" - et d'avoir une conversation avec lui. Au début de cette conversation, la télécommande répertorie toutes ses références: tout refs/heads/ce refs/tags/qu'il contient et tout ce qu'il contient, ainsi que toutes les autres références qu'il possède. Votre Git les analyse et (en se basant sur la refspec fetch habituelle) renomme leurs branches.

Jetons un coup d'œil à la spécification normale pour la télécommande nommée origin:

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

Cette spécification spécifie à votre Git de prendre chaque correspondance de refs/heads/*nom refs/remotes/origin/*- c'est- à -dire , chaque branche de la télécommande - et de changer son nom en , c'est- à -dire de garder la partie correspondante la même, en changeant le nom de la branche ( refs/heads/) en un nom de branche de suivi à distance ( refs/remotes/, spécifiquement , refs/remotes/origin/).

C'est grâce à cette refspec que originles branches deviennent vos branches de suivi à distance pour les télécommandes origin. Le nom de la branche devient le nom de la branche de suivi à distance, avec le nom de la télécommande, dans ce cas origin, inclus. Le signe plus +à l'avant de la spécification spécifie le drapeau "force", c'est-à-dire que votre branche de suivi à distance sera mise à jour pour correspondre au nom de la branche de la télécommande, indépendamment de ce qu'il faut pour la faire correspondre. (Sans le +, les mises à jour de branche sont limitées aux changements "d'avance rapide", et les mises à jour de balises sont simplement ignorées depuis la version 1.8.2 de Git environ - avant les mêmes règles d'avance rapide appliquées.)

Mots clés

Mais qu'en est-il des tags? Il n'y a pas de spécification pour eux, du moins pas par défaut. Vous pouvez en définir un, auquel cas la forme de la spécification vous appartient; ou vous pouvez courir git fetch --tags. L'utilisation --tagsa pour effet d'ajouter refs/tags/*:refs/tags/*à la refspec, c'est-à-dire qu'elle apporte toutes les balises ( mais ne met pas à jour votre balise si vous avez déjà une balise avec ce nom, indépendamment de ce que dit la balise de la télécommande Edit, Jan 2017: à partir de Git 2.10 , les tests montrent que --tagsles balises sont mises à jour de force à partir des balises de la télécommande, comme si la spécification était lue +refs/tags/*:refs/tags/*; cela peut être une différence de comportement par rapport à une version antérieure de Git).

Notez qu'il n'y a pas de renommage ici: si remote origina une balise xyzzy, et vous ne l'avez pas, et vous git fetch origin "refs/tags/*:refs/tags/*", vous êtes refs/tags/xyzzyajouté à votre référentiel (pointant vers le même commit que sur la remote). Si vous utilisez +refs/tags/*:refs/tags/*alors votre balise xyzzy, si vous en avez une, est remplacée par celle de origin. C'est-à-dire que l' +indicateur de force sur une refspec signifie "remplacer la valeur de ma référence par celle que mon Git obtient de son Git".

Balises automagiques lors de la récupération

Pour des raisons historiques, 3 si vous n'utilisez ni l' --tagsoption ni l' --no-tagsoption, git fetchprend des mesures spéciales. N'oubliez pas que nous avons dit ci-dessus que la télécommande commence par afficher sur votre Git local toutes ses références, que votre Git local veuille les voir ou non. 4 Votre Git prend note de toutes les balises qu'il voit à ce stade. Ensuite, alors qu'il commence à télécharger les objets de validation dont il a besoin pour gérer tout ce qu'il récupère, si l'une de ces validations a le même ID que l'une de ces balises, git ajoutera cette balise - ou ces balises, si plusieurs balises ont cet ID - à votre référentiel.

Edition, janvier 2017: Les tests montrent que le comportement dans Git 2.10 est maintenant: Si leur Git fournit une balise nommée T , et vous n'avez pas une balise nommée T , et la validation ID associé à T est un ancêtre d'une de leurs branches que vous git fetchexaminez, votre Git ajoute T à vos balises avec ou sans --tags. L'ajout --tagsoblige votre Git à obtenir toutes ses balises et force également la mise à jour.

Conclusion

Vous devrez peut-être utiliser git fetch --tagspour obtenir leurs balises. Si leurs noms de balises entrent en conflit avec vos noms de balises existants, vous pouvez (selon la version de Git) même supprimer (ou renommer) certaines de vos balises, puis exécuter git fetch --tags, pour obtenir leurs balises. Étant donné que les balises, contrairement aux branches distantes, n'ont pas de renommage automatique, vos noms de balises doivent correspondre à leurs noms de balises, c'est pourquoi vous pouvez rencontrer des problèmes avec les conflits.

Dans la plupart des cas normaux, cependant, un simple git fetchfera le travail, en apportant leurs validations et leurs balises correspondantes, et puisqu'ils - qui qu'ils soient - marqueront les validations au moment où ils publieront ces validations, vous suivrez leurs balises. Si vous ne créez pas vos propres balises, ni ne mélangez leur référentiel et d'autres référentiels (via plusieurs télécommandes), vous n'aurez pas non plus de collision de noms de balises, vous n'aurez donc pas à vous soucier de supprimer ou de renommer des balises afin de obtenir leurs étiquettes.

Lorsque vous avez besoin de noms qualifiés

Je l' ai mentionné ci - dessus que vous pouvez omettre refs/presque toujours, et refs/heads/et refs/tags/et ainsi de suite la plupart du temps. Mais quand ne le pouvez- vous pas ?

La réponse complète (ou presque complète de toute façon) se trouve dans la gitrevisionsdocumentation . Git résoudra un nom en ID de validation en utilisant la séquence en six étapes indiquée dans le lien. Curieusement, les balises remplacent les branches: s'il y a une balise xyzzyet une branche xyzzy, et qu'elles pointent vers des validations différentes, alors:

git rev-parse xyzzy

vous donnera l'ID vers lequel pointe le tag. Cependant - et c'est ce qui manque gitrevisions- git checkoutpréfère les noms de branche, donc git checkout xyzzyvous mettra sur la branche, sans tenir compte de la balise.

En cas d'ambiguïté, vous pouvez presque toujours épeler le nom ref en utilisant son nom complet, refs/heads/xyzzyou refs/tags/xyzzy. (Notez que cela fait travailler avec git checkout, mais d'une manière peut - être inattendue: git checkout refs/heads/xyzzyprovoque un départ-HEAD individuelle plutôt que d' une caisse de branche Ceci est la raison pour laquelle il vous suffit de noter que. git checkoutUtilisera le nom court comme nom de la branche première: qui est la façon dont vous extraire la branche xyzzymême si la balise xyzzyexiste. Si vous souhaitez extraire la balise, vous pouvez l'utiliser refs/tags/xyzzy.)

Parce que (comme des gitrevisionsnotes) Git va essayer , vous pouvez aussi simplement écrire pour identifier le commit balisé . (Si quelqu'un a réussi à écrire une référence valide nommée dans , cependant, cela se résoudra en . Mais normalement, seuls les différents noms doivent être inclus .)refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


1 D'accord, d'accord, "pas seulement pour être pédant". :-)

2 Certains diraient «très inutile», et j'aurais tendance à être d'accord, en fait.

3 Fondamentalement, git fetchet tout le concept des télécommandes et des refspecs, était un peu un ajout tardif à Git, se produisant à l'époque de Git 1.5. Avant cela, il n'y avait que quelques cas spéciaux ad hoc, et la récupération de balises en faisait partie, donc il a été protégé par un code spécial.

4 Si cela peut vous aider, considérez le Git distant comme un clignotant , dans le sens de l'argot.

torek
la source
Grand résumé. Un petit nit: git fetchne récupérera que les balises de la télécommande en fonction de l' --tagsarg.
semaines
@cweekly: le comportement --tags, --no-tagset par défaut est en fait assez difficile. La valeur par défaut est d'introduire des balises que vous n'avez pas dans les commits que vous apportez. (Voir l'édition de janvier 2017.) Mais il y a aussi des problèmes ici, et Git moderne a ses --tags / - Le code de gestion des non-balises a encore été révisé, ce qui entraînera probablement des cas d'angle encore plus spéciaux.
torek
1

Pour extraire une balise git, vous devez exécuter la commande suivante

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

par exemple, comme mentionné ci-dessous.

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

Pour récupérer toutes les balises, utilisez la commande

git fetch --all --tags
mani
la source
0

Pour obtenir le code d'étiquette spécifique, essayez de créer une nouvelle branche, ajoutez-y le code d'étiquette. Je l'ai fait par commande:$git checkout -b newBranchName tagName

Rahul Khatri
la source