Comment renommer une balise Git?

1219

Aujourd'hui, je regardais les journaux d'un projet et j'ai réalisé qu'il y a quelque temps, j'ai touché le nom d'une étiquette. Existe-t-il un moyen de renommer la balise? Google n'a rien trouvé d'utile.

Je me rends compte que je pouvais vérifier la version étiquetée et créer une nouvelle étiquette, j'ai même essayé. Mais cela semble créer un objet tag qui n'est pas tout à fait correct. Pour un,

git tag -l

la répertorie dans le désordre par rapport à toutes les autres balises. Je ne sais pas si c'est important, mais cela me porte à croire que le nouvel objet tag n'est pas tout à fait ce que je veux. Je peux vivre avec ça, car je me soucie vraiment que le nom de la balise corresponde à la documentation, mais je préfère le faire "bien", en supposant qu'il existe une bonne façon de le faire.

Brandon Fosdick
la source
Avez-vous utilisé la même invocation, c'est-à-dire si l'ancienne balise était une balise annotée / signée, la nouvelle balise est-elle également de ce type ou est-ce une balise légère?
Jakub Narębski
1
L'ancienne balise incorrecte et la nouvelle balise souhaitée doivent être annotées et non signées. L'ancienne balise a été créée avec 'git tag -a bad_tag_name', donc je voudrais faire quelque chose comme 'git tag -a good_tag_name'.
Brandon Fosdick
Je dois souligner que je souhaite également que ce processus de changement de nom de balise magique préserve l'annotation de la balise en cours de changement de nom. En fait, je voudrais vraiment changer juste le nom et rien d'autre.
Brandon Fosdick
7
git log --oneline --decorate --graphest utile lors du nettoyage des balises.
Joel Purra
Vous pouvez renommer un tag sur une seule ligne: voir ma réponse ci
VonC

Réponses:

2040

Voici comment je renomme une étiquette oldà new:

git tag new old
git tag -d old
git push origin :refs/tags/old
git push --tags

Le signe deux-points dans la commande push supprime la balise du référentiel distant. Si vous ne le faites pas, Git créera l'ancienne balise sur votre machine lorsque vous tirerez.

Enfin, assurez-vous que les autres utilisateurs suppriment la balise supprimée. Veuillez leur dire (collègues) d'exécuter la commande suivante:

git pull --prune --tags

Notez que si vous modifiez une balise annotée , vous devez vous assurer que le nouveau nom de balise fait référence à la validation sous-jacente et non à l'ancien objet de balise annoté que vous êtes sur le point de supprimer. Par conséquent, utilisez git tag -a new old^{}plutôt git tag new old(c'est parce que les balises annotées sont des objets alors que les balises légères ne le sont pas, plus d'informations dans cette réponse ).

Casey Watson
la source
19
si la balise est annotée, la nouvelle balise n'aura pas le message de l'ancienne, mais c'est une info utile
NickSoft
25
@NickSoft, je viens de faire ce qui précède avec des balises annotées. Les messages ont été copiés de l'ancien au nouveau très bien. Peut-être que j'ai une version plus récente de git?
katyhuff
25
git push origin :refs/tags/oldpeut être simplifié git push origin :oldje pense.
Jesse Glick
25
Je suggérerais de changer "git push --tags" pour être plus explicite à cette balise "git push origin refs / tags / new". Vous ne voulez pas pousser par inadvertance d'autres balises.
chrish
11
Avertissement : L'utilisation git tag new oldcréera une balise pointant vers l'ancienne balise, pas le commit de l'ancienne balise. (Voir Pourquoi ne puis-je pas retirer mon tag depuis Git GUI? )
Stevoisiak
297

La question initiale était de savoir comment renommer une étiquette, qui est facile: tout d' abord créer un nouveau comme un alias de vieux: git tag NEW OLDsupprimez VIEUX: git tag -d OLD.

La citation concernant "la manière Git" et (in) la raison est hors de propos, car il s'agit de préserver un nom de balise, mais de le faire référence à un état de référentiel différent.

Greg McGary
la source
3
La réponse ci-dessus est légèrement préférable car elle inclut l' git push originentreprise.
Roly
manière la plus simple, fonctionne très bien pour renommer une balise de version précédente créée avec Gitflow
RousseauAlexandre
5
Avertissement : L'utilisation git tag new oldcréera une balise pointant vers l'ancienne balise, pas le commit de l'ancienne balise. (Voir Pourquoi ne puis-je pas retirer mon tag depuis Git GUI? )
Stevoisiak
118

En plus des autres réponses:

Vous devez d'abord créer un alias de l' ancien nom de la balise, pointant vers le commit d'origine:

git tag new old^{}

Ensuite, vous devez supprimer l'ancien localement :

git tag -d old

Ensuite, supprimez la balise sur vos emplacements distants:

# Check your remote sources:
git remote -v
# The argument (3rd) is your remote location,
# the one you can see with `git remote`. In this example: `origin`
git push origin :refs/tags/old

Enfin, vous devez ajouter votre nouvelle balise à l'emplacement distant. Jusqu'à ce que vous ayez fait cela, les nouvelles balises ne seront pas ajoutées:

git push origin --tags

Répétez cela pour chaque emplacement distant.

Soyez conscient des implications d'un changement de Git Tag pour les consommateurs d'un package!

kaiser
la source
Avertissement : L'utilisation git tag new oldcréera une balise pointant vers l'ancienne balise, pas le commit de l'ancienne balise. (Voir Pourquoi ne puis-je pas retirer mon tag depuis Git GUI? )
Stevoisiak
1
@StevenVascellaro Merci pour le lien. Pour la prochaine fois, veuillez déposer une modification - la réponse est également un effort de la communauté. Merci.
kaiser
Je n'ai pas fait de modification car je n'ai pas encore testé le code pour moi. (Notez la date de soumission sur la question liée)
Stevoisiak
Une fois que nous le faisons git tag new old^{}, alors nous n'avons pas besoin git tag new_tag_name old_tag_name(la première étape).
Number945
28

S'il est publié, vous ne pouvez pas le supprimer (sans risquer d'être goudronné et à plumes, c'est-à-dire). La «manière Git» est de faire:

La chose sensée. Admettez simplement que vous avez foiré et utilisez un nom différent. D'autres ont déjà vu un nom de balise, et si vous gardez le même nom, vous pourriez être dans la situation où deux personnes ont toutes les deux la "version X", mais elles ont en fait des "X" différents. Il suffit donc de l'appeler "X.1" et d'en finir.

Alternativement,

La chose folle. Vous voulez vraiment appeler la nouvelle version "X" aussi, même si d'autres ont déjà vu l'ancienne. Utilisez donc à nouveau git-tag -f, comme si vous n'aviez pas déjà publié l'ancien.

C'est tellement fou parce que:

Git ne change pas (et ne devrait pas) changer les balises derrière les utilisateurs. Donc, si quelqu'un a déjà obtenu l'ancienne balise, faire un git-pull sur votre arbre ne devrait pas simplement les faire écraser l'ancienne.

Si quelqu'un a obtenu une balise de sortie de votre part, vous ne pouvez pas simplement la modifier en mettant à jour la vôtre. C'est un gros problème de sécurité, dans la mesure où les gens DOIVENT être en mesure de faire confiance à leurs noms de balises. Si vous voulez vraiment faire la chose folle, il vous suffit de vous en rendre compte et de dire aux gens que vous avez foiré.

Toute la courtoisie des pages de manuel .

Robert Munteanu
la source
6
Ou vous pouvez étiqueter (avec le nom correct) cette étiquette mal nommée.
Jakub Narębski
6
Merci, j'ai déjà parcouru cette page de manuel un million de fois. Heureusement, la mauvaise balise n'a été publiée nulle part. Même si c'était le cas, c'est un projet interne et je suis le seul développeur (pour le moment). Je pense que je suis assez à l'abri des goudrons et des plumes, mais seulement si je peux obtenir le dépôt correspondant aux documents.
Brandon Fosdick
J'utilise parfois des balises pour mes propres références personnelles. Par exemple. il pourrait s'agir d'une balise «ok_jb». J'utilise ceci, car certaines des personnes avec lesquelles je travaille ne peuvent pas construire pour ma plate-forme, donc parfois il y aura des erreurs de construction. Je peux ensuite obtenir rapidement une version qui se construit, en vérifiant cette balise. Lorsque les nouvelles sources se construisent, je déplace simplement la balise, ou je la renomme en builds ##, où ## est un nombre (selon le projet). Je peux également souligner quand une fonctionnalité spéciale a été introduite, en ajoutant une balise.
7
Mauvaise réponse. "Ne le faites pas" n'est jamais la bonne réponse à "Comment puis-je le faire?". L'utilisateur ne demandait pas si vous pensez que c'était une bonne idée de le faire ou si les gens aimeraient ça. Si quelqu'un demande "Comment puis-je me couper la main", dites-lui comment c'est fait ou laissez-le tranquille, mais il n'aura pas besoin que quelqu'un lui dise que se couper la main n'est peut-être pas une si bonne idée. Et vous pouvez le faire. Vous pouvez ajouter une nouvelle balise et supprimer l'ancienne, c'est techniquement possible, même dans un référentiel distant.
Mecki
5
Cela semble répondre à la question "Comment puis-je faire pointer un tag existant vers une révision différente?" au lieu de la question de l'OP, "Comment renommer une étiquette?" Il est également difficile de savoir comment le fait de dire aux gens que vous avez foiré va résoudre le problème (même si c'est une bonne idée en général).
LarsH
25

Cette page wiki a cet intéressant one-liner, qui nous rappelle que nous pouvons pousser plusieurs refs :

git push origin <refs/tags/old-tag>:<refs/tags/new-tag> :<refs/tags/old-tag> && git tag -d <old-tag>

et demander aux autres cloners de faire git pull --prune --tags

L'idée est donc de pousser:

  • <new-tag>pour tous les commits référencés par <old-tag>: <refs/tags/old-tag>:<refs/tags/new-tag>,
  • la suppression de<old-tag> ::<refs/tags/old-tag>

Voir comme exemple " Changer la convention de nommage des balises à l'intérieur d'un référentiel git? ".

VonC
la source
Cela préserve-t-il les annotations?
Brandon Fosdick
1
Attention, cela laisse le nom de la balise d'origine dans l'annotation des balises annotées !! Je ne sais pas si cela implique réellement quoi que ce soit, au moins dans les versions actuelles.
gbr
@gbr Pouvez-vous modifier la réponse avec un exemple montrant que "nom de balise d'origine" laissé dans l'annotation?
VonC
1
@VonC Je ne suis pas sûr de comprendre ce que vous demandez; peut-être que je n'étais pas clair: les objets d'annotation contiennent un champ de balise qui est défini sur le nom de la balise, vous pouvez le voir avec git cat-file -p <tag>; avec votre méthode sur mon système, je reçois la balise «renommée» ref ( <new-tag>), mais son champ de balise est toujours <old-tag>.
gbr
3
@gbr N'est-ce pas ce que voulait l'OP? Il a mentionné «Je dois souligner que je souhaite également que ce processus de changement de nom de balise magique préserve l'annotation de la balise en cours de changement de nom. En fait, je voudrais vraiment changer uniquement le nom et rien d'autre» ( stackoverflow.com/questions/1028649/ comment-vous-renommer-un-git-tag /… )
VonC
25

En complément des autres réponses, j'ai ajouté un alias pour tout faire en une seule étape, avec une sensation de commande de déplacement * nix plus familière. L'argument 1 est l'ancien nom de la balise, l'argument 2 est le nouveau nom de la balise.

[alias]
    renameTag = "!sh -c 'set -e;git tag $2 $1; git tag -d $1;git push origin :refs/tags/$1;git push --tags' -"

Usage:

git renametag old new
Jared Knipp
la source
Cela n'a pas fonctionné pour moi, car il a échoué à !sh(question était À propos de Windows Git), cependant, après la mise à jour du format à ce qui suit, il a travaillé: renametag = "!f() { git tag $2 $1; git tag -d $1; git push origin :refs/tags/$1; git push --tags; }; f".
Sunny Patel
10

Suivez l'approche en 3 étapes pour une ou plusieurs balises.

Étape 1: identifier l'ID de validation / objet de la validation vers laquelle pointe la balise actuelle

     command: git rev-parse <tag name>
     example: git rev-parse v0.1.0-Demo
     example output: db57b63b77a6bae3e725cbb9025d65fa1eabcde

Étape 2: supprimer la balise du référentiel

     command: git tag -d <tag name>
     example: git tag -d v0.1.0-Demo
     example output: Deleted tag 'v0.1.0-Demo' (was abcde)

Étape 3: créer une nouvelle balise pointant vers le même ID de validation que l'ancienne balise pointait vers

     command: git tag -a <tag name>  -m "appropriate message" <commit id>
     example: git tag -a v0.1.0-full  -m "renamed from v0.1.0-Demo" db57b63b77a6bae3e725cbb9025d65fa1eabcde
     example output: Nothing or basically <No error>

Une fois que le git local est prêt avec le changement de nom de balise, ces changements peuvent être repoussés à l'origine pour que d'autres les prennent.

vikas pachisia
la source
Il manque des étapes pour repousser la balise supprimée: git push origin :refs/tags/v0.1.0-Demoet pour repousser les balises (avec d'autres choses en attente)git push --tags
Star Wolf
6

Pour les aventuriers, cela peut être fait en une seule commande:

mv .git/refs/tags/OLD .git/refs/tags/NEW
Wolfc
la source
7
Cela ne fonctionnera pas si vos références sont emballées, c'est-à-dire si vous avez exécuté git gcrécemment
forivall
2
Cela n'affectera également que le dépôt local. Si vous avez une télécommande configurée, je ne sais pas quels effets négatifs cela pourrait provoquer. Je ne recommande pas cette approche.
therealklanni
1
Notez également que pour les balises annotées, cela sera probablement encore plus gênant, car le blob «annotation» contient, entre autres, le nom d'origine de la balise. En fait, je ne sais pas si c'est utilisé par quoi que ce soit (du moins, espérons-le, par Verify-tag), mais je ne prendrais pas de chance.
gbr
1
@gbr Cela fonctionne très bien. (Bien sûr, la note de @forivall doit être prise en compte.) Cette astuce a été massivement utilisée pendant des siècles dans le système de construction ALT Sisyphus. Regardez comment les sources d'un paquet sont stockées, par exemple: git.altlinux.org/gears/g/gear.git . Les balises lisibles comme 2.0.7-alt1 sont les balises signées soumises par les mainteneurs au système de construction. Les balises cryptiques gb-sisyphus-task164472.200 y sont mises par le système de construction pour suivre l'ID de tâche qui a construit et publié le paquet à partir de cette source. Ce sont des copies stupides ( cp), avec le message du responsable intact.
imz - Ivan Zakharyaschev
@ imz - IvanZakharyaschev Bon à savoir, je ne ferais pas trop confiance, mais cela ne posera pas de problèmes à l'avenir, avec certains produits; il n'y a pas de véritable spécification du format des référentiels git et de l'interaction attendue, donc quand c'est viable je m'efforcerais de faire les choses proprement de la manière la moins surprenante
gbr
3

Indépendamment des problèmes liés à la transmission des balises et au changement de nom des balises qui ont déjà été poussées, dans le cas où la balise à renommer est annotée , vous pouvez d'abord la copier grâce à la ligne de commande à ligne unique suivante:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}

Ensuite, il vous suffit de supprimer l'ancienne balise:

git tag -d old_tag

J'ai trouvé cette ligne de commande grâce aux deux réponses suivantes:

Edit:
Ayant rencontré des problèmes lors de la synchronisation automatique des paramètres de balises fetch.pruneTags=true(comme décrit dans https://stackoverflow.com/a/49215190/7009806 ), je suggère personnellement de copier d' abord la nouvelle balise sur le serveur, puis de supprimer l'ancienne. De cette façon, la nouvelle balise n'est pas supprimée de manière aléatoire lors de la suppression de l'ancienne balise et une synchronisation des balises voudrait supprimer la nouvelle balise qui n'est pas encore sur le serveur . Ainsi, par exemple, tous ensemble, nous obtenons:

git tag -a -m "`git cat-file -p old_tag | tail -n +6`" new_tag old_tag^{}
git push --tags
git tag -d old_tag
git push origin :refs/tags/old_tag
Olivier
la source
3

Vous pouvez également renommer des balises distantes sans les extraire, en dupliquant l'ancienne balise / branche à un nouveau nom et supprimez l'ancienne, en une seule git pushcommande.

Renommage tag à distance / branche à distance → conversion de tag: (Avis: :refs/tags/)

git push <remote_name> <old_branch_or_tag>:refs/tags/<new_tag> :<old_branch_or_tag>

Renommage branche à distance / tag distance → conversion de branche: (Avis: :refs/heads/)

git push <remote_name> <old_branch_or_tag>:refs/heads/<new_branch> :<old_branch_or_tag>

Sortie renommant une balise distante:

D:\git.repo>git push gitlab App%2012.1%20v12.1.0.23:refs/tags/App_12.1_v12.1.0.23 :App%2012.1%20v12.1.0.23

Total 0 (delta 0), reused 0 (delta 0)
To https://gitlab.server/project/repository.git
 - [deleted]               App%2012.1%20v12.1.0.23
 * [new tag]               App%2012.1%20v12.1.0.23 -> App_12.1_v12.1.0.23
zionyx
la source