Erreur "tag existe déjà dans la télécommande" après avoir recréé la balise git

142

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

To [email protected]:username/repo-name.git
 ! [rejected]        dev -> dev (already exists)
error: failed to push some refs to '[email protected]:username/repo-name.git'
hint: Updates were rejected because the tag already exists in the remote.
  1. Créé le référentiel
  2. Cloné le repo sur la machine locale.
  3. Modifier le fichier README, valider les modifications et pousser la validation.
  4. Balise créée dev:git tag dev
  5. Balises poussées: git push --tags
  6. Modifier le fichier README, valider les modifications et pousser la validation.
  7. Balise supprimée dev, créée à nouveau et poussée des balises:

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

Pourquoi cela arrive-t-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 -fpour forcer la mise à jour de la balise, mais c'est dangereux (par exemple, réécrire un commit fait par erreur uniquement dans la balise, pas dans la branche).

Luca Boieru
la source
1
Les validations ne sont pas effectuées "dans les balises" ou "dans les branches" (même si cela semble être le cas). En fait, les noms de balises et de branches pointent simplement vers (un, unique) commit. Voir la réponse ci-dessous.
torek
8
cela a fonctionné pour moi git pull --tagsalorsgit push origin --tags
sawe

Réponses:

175

Edit, 24 novembre 2016: cette réponse est apparemment populaire, j'ajoute donc une note ici. Si vous remplacez une balise sur un serveur central, toute personne qui possède l' ancienne balise (tout clone de ce référentiel de serveur central qui a déjà la balise) peut conserver son ancienne balise . Donc, bien que cela vous indique comment le faire, soyez vraiment sûr de vouloir le faire. Vous devrez demander à toutes les personnes qui ont déjà la «mauvaise» balise de supprimer leur «mauvaise balise» et de la remplacer par la nouvelle «bonne balise».

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

(La réponse originale suit.)


Lorsque vous demandez de pousser des balises, git push --tagsenvoie (avec tous les commits et autres objets nécessaires et toutes les autres mises à jour de référence à partir des paramètres push) à la télécommande une demande de mise à jour du formulaire . (Eh bien, il en envoie autant: un de ceux pour chaque tag.)new-sha1 refs/tags/name

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

La old-sha1valeur est le SHA-1 «nul» tout zéros si la balise est en cours de création. Le new-sha1est 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 "hook 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 "hook intégré" soit toujours OK avec les deux "ajouter" et "supprimer"). Le message de rejet que vous voyez provient de ce hook intégré. (Incidemment, ce même hook intégré rejette également les mises à jour de branche qui ne sont pas rapides.) 1

Mais - voici l'une des clés pour comprendre ce qui se passe - l' git pushétape n'a aucune idée si la télécommande a cette balise maintenant, et si oui, quelle valeur SHA-1 elle a. Il dit seulement "voici ma liste complète de balises, avec leurs valeurs SHA-1". La télécommande compare les valeurs et s'il y a des ajouts et / ou des modifications, exécute les hooks sur celles-ci. (Pour les balises identiques, cela ne fait rien du tout. Pour les balises que vous n'avez pas, cela ne fait rien non plus!)

Si vous supprimez la balise localement, pushvotre push ne transfère tout simplement pas la balise. La télécommande suppose qu'aucune modification ne doit être apportée.

Si vous supprimez la balise localement, puis créez-la en pointant vers un nouvel emplacement, alors push, votre push transfère la balise, et la télécommande voit cela comme un changement de balise et rejette la modification, à moins que ce ne soit une poussée forcée.

Ainsi, vous avez deux options:

  • faire une poussée forcée, ou
  • supprimez l'étiquette de la télécommande.

Cette dernière est possible via git push2 même si la suppression de la balise localement et pushing n'a aucun effet. En supposant que le nom de la télécommande est originet que la balise que vous souhaitez supprimer 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 devdans votre référentiel local n'est pas pertinente; ce genre de push, avec comme refspec, est une pure suppression.:remoteref

La télécommande peut autoriser ou non la suppression de balises (en fonction des crochets supplémentaires ajoutés). Si cela permet la suppression, alors la balise disparaîtra, et une seconde git push --tags, lorsque vous avez une devbalise locale pointant vers un objet de repo de balises de validation ou annoté, envoyez votre nouvelle devbalise. Sur la télécommande, il y devaura désormais une balise nouvellement créée, donc la télécommande autorisera probablement le push (encore une fois, cela dépend de tout crochet supplémentaire ajouté).

La force-push est plus simple. Si vous voulez être sûr de ne mettre à jour autre chose que la balise, dites simplement git pushde ne pousser que cette refspec:

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

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


1 Bien sûr, la raison de ce hook intégré est d'aider à appliquer le comportement attendu par les autres utilisateurs de ce même dépôt distant: les branches ne sont pas rembobinées et les balises ne bougent pas. Si vous forcez, vous devez informer les autres utilisateurs que vous faites cela, afin qu'ils puissent y remédier. Notez que "les balises ne bougent pas du tout" est nouvellement appliquée par Git 1.8.2; les versions précédentes permettaient à la balise de "progresser" dans le graphe de validation, un peu comme les noms de branche. Consultez les notes de publication de git 1.8.2 .

2 C'est trivial si vous pouvez vous connecter sur la télécommande. Allez simplement dans le référentiel Git et exécutez git tag -d dev. Notez que dans les deux cas - en supprimant l'étiquette de la télécommande ou en utilisant git pushpour la supprimer - il y a une période pendant laquelle quiconque accède à la télécommande trouvera que l' devétiquette est manquante. (Ils continueront d'avoir leur propre ancienne balise, s'ils l'ont déjà, et ils pourraient même repousser leur ancienne balise avant que vous puissiez pousser la nouvelle.)

Torek
la source
Cela se produit-il uniquement dans les nouvelles versions de git? J'ai 1.7.9.5et je n'ai pas ce problème ...
Ionică Bizău
2
Probalby - Je me souviens vaguement d'avoir git push --tagssimplement changé la balise automatiquement dans les anciennes versions de git, sans --force. J'ai cependant testé cela sous la 1.8.4, et vous avez besoin de --forcela technique de mise à jour en deux étapes.
torek
2
@John ツ: mise à jour: c'est un nouveau comportement à partir de la 1.8.2, selon les notes de version . Je vais également le modifier dans la note de bas de page 1.
torek
Je ne sais pas comment je suis entré dans cette situation, mais une balise a été supprimée et recréée en un clin d'œil.
RiggsFolly
4
comment faire une poussée de force si vous n'êtes pas un jedi?
Fonix
54

Sous Mac SourceTree, décochez uniquement la case Push all tags :

entrez la description de l'image ici

Itzhar
la source
3
hahahah homme si simple, je lisais la réponse acceptée et je pensais que je vais tellement tromper ça
MegaManX
10
Il s'agit simplement de le surmonter sans vraiment résoudre le problème. Cela ne résout pas la correspondance du nom de balise à distance et en local.
amalBit
1
fonctionne également pour la version Windows! merci de nous avoir sauvés de la lecture de la réponse acceptée depuis longtemps qui omet les utilisateurs de sourcetree qui ne se soucient pas de ce qui se passe dans l'invite de commande :)
schlingel
19

C'est assez simple si vous utilisez SourceTree .

entrez la description de l'image ici En gros, il vous suffit de supprimer et de rajouter la balise en conflit:

  1. Aller à l'onglet Repository -> Tag -> Remove Tag
  2. Sélectionnez le nom de balise en conflit
  3. Cochez Supprimer l'étiquette de toutes les télécommandes
  4. Appuyez sur Supprimer
  5. Créez une nouvelle balise avec le même nom pour le bon commit
  6. Assurez-vous de cocher Pousser toutes les balises lorsque vous transmettez vos modifications à la télécommande
choofie
la source
16

Si vous souhaitez METTRE À JOUR un tag, disons-le1.0.0

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

TERMINÉ

Kaiyu Lee
la source
12

Il semble que je suis en retard sur ce problème et / ou il a déjà été répondu, mais, ce qui pourrait être fait est: (dans mon cas, je n'avais qu'une seule balise localement, donc .. J'ai supprimé l'ancienne balise et l'ai réajustée avec :

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

Ensuite:

git push --tags -f

Cela mettra à jour toutes les balises sur la télécommande.

Peut être dangereux! Utilisez à vos risques et périls.

André Tzermias
la source
1
Cela l'a fait pour moi! Les balises n'étaient que localement et pas dans la télécommande :)
pgarciacamou
4

La raison pour laquelle vous êtes rejeté est que votre balise a perdu la synchronisation avec la version distante. C'est le même comportement avec les branches.

synchronisez avec le tag de la télécommande via git pull --rebase <repo_url> +refs/tags/<TAG>et après la synchronisation, vous devez gérer les conflits . Si vous avez un diftool installé (ex. Meld)git mergetool meld utilisez-le pour synchroniser la télécommande et conserver vos modifications.

La raison pour laquelle vous tirez avec l' indicateur --rebase est que vous souhaitez placer votre travail au-dessus de celui distant afin d'éviter d'autres conflits.

De plus, ce que je ne comprends pas, c'est pourquoi supprimeriez-vous le devtag et le recréeriez ??? Les balises sont utilisées pour spécifier les versions ou les jalons du logiciel. Exemple de balises git v0.1dev, v0.0.1alpha, v2.3-cr(cr - libération des candidats) et ainsi de suite ..


Une autre façon de résoudre ce problème est le problème a git refloget de vous rendre au moment où vous avez poussé l' devétiquette sur la télécommande. Copiez l' ID de validation et git reset --mixed <commmit_id_from_reflog>vous saurez ainsi que votre balise était synchronisée avec la télécommande au moment où vous l'avez poussée et qu'aucun conflit ne surviendra.

Daniel Andrei Mincă
la source
Par exemple, si vous souhaitez baliser un commit qui est actuellement en production. Devriez-vous alors supprimer l'ancienne balise de production d'un commit spécifique, et créer et pousser une nouvelle balise pour le commit après la nouvelle version de production.
Ville Miekk-oja
2

Dans Windows SourceTree, décochez Push all tags to remotes.

entrez la description de l'image ici

Contango
la source
0

Quelques bonnes réponses ici. Surtout celui de @torek . J'ai pensé ajouter cette solution de contournement avec une petite explication pour ceux qui sont pressés.

Pour résumer, ce qui se passe, c'est que lorsque vous déplacez une balise localement, cela change la balise d'une valeur de validation non Null à une valeur différente. Cependant, comme git (par défaut) ne permet pas de changer les balises distantes non Null, vous ne pouvez pas pousser le changement.

La solution consiste à supprimer la balise (et à cocher supprimer toutes les télécommandes). Créez ensuite le même tag et appuyez sur.

idnavid
la source