158 votes

erreur "tag already exists in the remote" après avoir recréé le tag git

J'obtiens l'erreur suivante après avoir exécuté les étapes ci-dessous :

To git@provider.com:username/repo-name.git
 ! [rejected]        dev -> dev (already exists)
error: failed to push some refs to 'git@provider.com:username/repo-name.git'
hint: Updates were rejected because the tag already exists in the remote.
  1. Création du référentiel
  2. Cloner le repo sur la machine locale.
  3. Modifié le fichier README, commité les changements et poussé le commit.
  4. Balise créée dev : git tag dev
  5. Des tags poussés : git push --tags
  6. Modifié le fichier README, commité les changements et poussé le commit.
  7. Étiquette supprimée dev il l'a créé à nouveau et a poussé les tags :

    git tag -d dev
    git tag dev
    git push --tags

Pourquoi cela se produit-il ?

Je suis sur Mac. Mes amis qui utilisent Linux (Ubuntu) n'ont pas ce problème. Je sais que je peux utiliser git push --tags -f pour forcer la mise à jour de la balise, mais cela est dangereux (par exemple, réécrire un commit fait par erreur uniquement dans la balise, pas dans la branche).

2 votes

Les commits ne sont pas faits "dans les tags" ou "dans les branches" (même si on a l'impression que c'est le cas). En fait, les noms des balises et des branches sont simplement pointer vers (un, unique) engagement. S

10 votes

Cela a fonctionné pour moi git pull --tags puis git push origin --tags

0 votes

185voto

torek Points 25463

Edit, 24 nov 2016 : cette réponse est apparemment populaire, donc j'ajoute une note ici. Si vous remplacer une étiquette sur un serveur central, toute personne qui a le vieux n'importe quel clone de ce serveur central qui a déjà le tag pourrait conserver son ancienne étiquette . Donc, bien que cela vous indique comment faire, assurez-vous que vous veulent pour le faire. Vous devez faire en sorte que tous ceux qui ont déjà la "mauvaise" étiquette suppriment leur "mauvaise étiquette" et la remplacer par la nouvelle "bonne étiquette".

Les tests effectués dans Git 2.10/2.11 montrent que la conservation de l'ancienne balise est le comportement par défaut pour les clients qui exécutent le programme. git fetch et la mise à jour est le comportement par défaut pour les clients qui exécutent le programme git fetch --tags .

(La réponse originale suit.)


Quand vous demandez de pousser les balises, git push --tags envoie (avec tous les commits et autres objets nécessaires et toutes les autres mises à jour ref des paramètres du push) au distant une demande de mise à jour de la forme _new-sha1_ refs/tags/_name_ . (En fait, il en envoie un nombre illimité : un pour chaque balise).

La demande de mise à jour est modifiée par le distant pour ajouter un old-sha1 (ou encore, un pour chaque balise), puis transmis aux crochets de pré-réception et/ou de mise à jour (selon les crochets existant sur la télécommande). Ces hooks peuvent décider d'autoriser ou de rejeter la création/suppression/mise à jour de l'étiquette.

El old-sha1 est la valeur SHA-1 entièrement zeros "null" si la balise est en cours de création. L'adresse new-sha1 est le SHA-1 nul si la balise est supprimée. Sinon, les deux valeurs SHA-1 sont des valeurs réelles et valides.

Même sans crochet, il y a une sorte de "crochet intégré" qui est également exécuté : la télécommande refusera de déplacer une balise à moins que vous n'utilisiez le drapeau "force" (bien que le "crochet intégré" soit toujours OK avec "add" et "delete"). Le message de rejet que vous voyez provient de ce crochet intégré. (Incidemment, ce même hook intégré rejette également les mises à jour de branches qui ne sont pas des avances rapides). 1

Mais - voici une des clés pour comprendre ce qui se passe - git push step n'a aucune idée si la télécommande a ce tag maintenant, et si oui, quelle valeur SHA-1 il a. Elle dit seulement "voici ma liste complète de tags, avec leurs valeurs SHA-1". Le distant compare les valeurs et s'il y a des ajouts et/ou des changements, il exécute les hooks sur ceux-ci. (Pour les tags qui sont les mêmes, il ne fait rien du tout. Pour les balises que vous n'avez pas et qu'ils ont, il ne fait rien non plus).

Si vous supprimez la balise localement, alors push votre poussée ne transfère tout simplement pas l'étiquette. La télécommande suppose qu'aucun changement ne doit être effectué.

Si vous supprimez la balise localement, puis la créez en pointant vers un nouvel endroit, alors push votre poussée transfère la balise, et la télécommande voit cela comme un changement de balise et rejette le changement, à moins qu'il s'agisse d'une poussée forcée.

Ainsi, vous avez deux options :

  • faire une poussée, ou
  • supprimer le tag sur la télécommande.

Ce dernier est possible via git push 2 même si la suppression de l'étiquette localement et push n'a aucun effet. En supposant que le nom de la télécommande est origin et la balise que vous voulez qu'il supprime est dev :

git push origin :refs/tags/dev

Cela demande à la télécommande de supprimer la balise. La présence ou l'absence de la balise dev dans votre dépôt local n'est pas pertinent ; ce genre de push avec :_remoteref_ en tant que spécification de référence, est une poussée de suppression pure.

La télécommande peut permettre ou non la suppression des balises (en fonction des crochets supplémentaires ajoutés). S'il autorise la suppression, alors la balise sera supprimée, et une seconde balise git push --tags quand vous avez un local dev pointant vers un commit ou un objet repo annoté, envoyez votre nouvelle balise dev tag. Sur la télécommande, dev sera désormais une balise nouvellement créée, de sorte que la télécommande autorisera probablement le push (cela dépend à nouveau des crochets supplémentaires ajoutés).

La force-poussée est plus simple. Si vous voulez être sûr de ne pas mettre à jour quoi que ce soit autre que l'étiquette, dites simplement git push pour ne pousser que cette seule refspec :

git push --force origin refs/tags/dev:refs/tags/dev

(note : vous n'avez pas besoin --tags si vous poussez explicitement une seule balise ref-spec).


1 Bien sûr, le raison pour ce hook intégré est d'aider à faire respecter le comportement que les autres utilisateurs de ce même remote-repo attendent : que les branches ne soient pas rembobinées, et que les tags ne se déplacent pas. Si vous faites du forcing, vous devez faire savoir aux autres utilisateurs que vous faites cela, afin qu'ils puissent le corriger. Notez que "les balises ne bougent pas du tout" est nouvellement appliqué par Git 1.8.2 ; les versions précédentes permettaient à la balise d'"avancer" dans le graphe de commit, tout comme les noms de branches. Voir le Notes de publication de git 1.8.2 .

2 C'est trivial si vous pouvez vous connecter sur la télécommande. Il suffit d'aller sur le dépôt Git et d'exécuter git tag -d dev . Notez que, quelle que soit la méthode utilisée - effacer la balise sur la télécommande ou utiliser la fonction git push pour l'effacer - il y a une période de temps pendant laquelle toute personne qui accède à la télécommande trouvera que la dev est manquante. (Ils continueront à avoir leur propre ancienne étiquette, s'ils l'ont déjà, et ils pourraient même pousser leur l'ancienne balise doit être remontée avant que vous puissiez pousser la nouvelle).

0 votes

Cela se produit-il uniquement dans les nouvelles versions de git ? J'ai 1.7.9.5 et je n'ai pas ce problème...

2 votes

Probalby J'ai un vague souvenir de git push --tags simplement changer la balise automatiquement dans les anciennes versions de git, sans --force . J'ai testé cela sous la version 1.8.4, et vous avez besoin de --force ou la technique de mise à jour en deux étapes.

2 votes

@John : mise à jour : c'est un nouveau comportement à partir de la version 1.8.2, d'après le site Web de la Commission européenne. notes de mise à jour . Je vais aussi éditer ceci dans la note de bas de page 1.

58voto

itzhar Points 36

Dans Mac SourceTree, ne désélectionnez que l'option Pousser tous les tags la case à cocher :

enter image description here

4 votes

Hahahahah si simple mec, je lisais la réponse acceptée et je pensais que j'allais la truquer.

12 votes

Il s'agit juste de surmonter le problème sans le résoudre réellement. Cela ne résout pas le problème de non-concordance des noms de balises à distance et en local.

1 votes

Fonctionne aussi pour la version Windows ! merci de nous éviter de lire la longue réponse acceptée qui omet les utilisateurs de Sourcetree qui ne se soucient pas de ce qui se passe dans l'invite de commande :)

22voto

choofie Points 727

C'est assez simple si vous utilisez SourceTree .

enter image description here En fait, il suffit de supprimer et de réintroduire la balise en conflit :

  1. Aller à l'onglet Référentiel -> Étiquette -> Retirer l'étiquette
  2. Sélectionnez le nom du tag en conflit
  3. Vérifiez Retirer l'étiquette de toutes les télécommandes
  4. Appuyez sur Retirer
  5. Créer un nouveau tag avec le même nom pour le bon commit
  6. Assurez-vous de vérifier Pousser tous les tags lors de l'envoi de vos modifications à distance

19voto

Kaiyu Lee Points 483

Si vous voulez UPDATE une étiquette, disons que 1.0.0

  1. git checkout 1.0.0
  2. faites vos changements
  3. git ci -am 'modify some content'
  4. git tag -f 1.0.0
  5. supprimer le tag distant sur github : git push origin --delete 1.0.0
  6. git push origin 1.0.0

FAIT

19voto

André Tzermias Points 842

Il semble que je sois en retard sur cette question et/ou qu'elle ait déjà été traitée, mais, ce qui pourrait être fait est : (dans mon cas, je n'avais qu'un seul tag en local donc.. J'ai supprimé l'ancien tag et l'ai retagué avec :

git tag -d v1.0
git tag -a v1.0 -m "My commit message"

Ensuite :

git push --tags -f

Cela mettra à jour tous des tags à distance.

Cela pourrait être dangereux ! A utiliser à vos risques et périls.

1 votes

Cela l'a fait pour moi ! Les balises n'étaient que locales et pas dans la télécommande :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X