Errore "tag già esistente nel telecomando" dopo aver ricreato il tag git


142

Ottengo il seguente errore dopo aver eseguito i passaggi seguenti:

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. Creato il repository
  2. Clonato il repository sul computer locale.
  3. Modificato il file README, eseguito il commit delle modifiche e inviato il commit.
  4. Tag creato dev:git tag dev
  5. Tag push: git push --tags
  6. Modificato il file README, eseguito il commit delle modifiche e inviato il commit.
  7. Tag eliminato dev, creato nuovamente e push tag:

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

Perché sta succedendo?

Sono su Mac. I miei amici che usano Linux (Ubuntu) non hanno questo problema. So che posso usare git push --tags -fper forzare l'aggiornamento del tag, ma questo è pericoloso (ad esempio riscrivere un commit fatto per errore solo nel tag, non nel ramo).


1
I commit non vengono eseguiti "nei tag" o "nei rami" (anche se sicuramente sembra che quest'ultimo sia il caso). In effetti, i nomi dei tag e dei rami indicano semplicemente (uno, singolo) commit. Vedi la risposta sotto.
Torek,

8
questo ha funzionato per me git pull --tagsalloragit push origin --tags
visto il

Risposte:


175

Modifica, 24 nov 2016: questa risposta è apparentemente popolare, quindi sto aggiungendo una nota qui. Se si sostituisce un tag su un server centrale, chiunque abbia il vecchio tag, qualsiasi clone di quel repository del server centrale che già ha il tag, potrebbe conservare il suo vecchio tag . Quindi, mentre questo ti dice come farlo, assicurati davvero di volerlo fare. Dovrai ottenere tutti coloro che hanno già il tag "sbagliato" per eliminare il loro "tag sbagliato" e sostituirlo con il nuovo "tag giusto".

I test in Git 2.10 / 2.11 mostrano che il mantenimento del vecchio tag è il comportamento predefinito per i client in esecuzione git fetche l'aggiornamento è il comportamento predefinito per i client in esecuzione git fetch --tags.

(Segue la risposta originale.)


Quando chiedi di git push --tagsinviare tag, invia (insieme a eventuali commit e altri oggetti necessari e qualsiasi altro aggiornamento ref dalle impostazioni push) al telecomando una richiesta di aggiornamento del modulo . (Bene, ne invia comunque molti: uno di quelli per ogni tag.)new-sha1 refs/tags/name

La richiesta di aggiornamento viene modificata dal telecomando per aggiungere una old-sha1(o ancora una volta per ogni tag), quindi consegnata agli hook di pre-ricezione e / o aggiornamento (qualunque hook presenti sul telecomando). Questi hook possono decidere se consentire o rifiutare il tag create / delete / update.

Il old-sha1valore è SHA-1 "null" di tutti gli zeri se il tag viene creato. Il new-sha1è il nulla SHA-1 se il tag viene cancellato. In caso contrario, entrambi i valori SHA-1 sono valori reali e validi.

Anche senza hook, esiste anche una sorta di "hook incorporato": il telecomando rifiuterà di spostare un tag a meno che non si usi il flag "force" (sebbene il "hook incorporato" sia sempre OK con entrambi "aggiungi" ed "elimina"). Il messaggio di rifiuto che stai vedendo proviene da questo hook integrato. (Per inciso, questo stesso hook incorporato rifiuta anche gli aggiornamenti delle filiali che non sono rapidi.) 1

Ma — ecco una delle chiavi per capire cosa sta succedendo — il git pushpasso non ha idea se il telecomando abbia quel tag ora e, in tal caso, quale valore SHA-1 ha. Dice solo "ecco il mio elenco completo di tag, insieme ai loro valori SHA-1". Il telecomando confronta i valori e se ci sono aggiunte e / o modifiche, esegue i ganci su quelli. (Per i tag che sono uguali, non fa nulla. Per i tag che non hai, non fa nulla!)

Se elimini il tag localmente, quindi push, il tuo push semplicemente non trasferisce il tag. Il telecomando presuppone che non sia necessario apportare modifiche.

Se elimini il tag localmente, quindi lo crei puntando a un nuovo posto, quindi push, il tuo push trasferisce il tag e il telecomando lo vede come un cambio di tag e rifiuta il cambiamento, a meno che non sia un push forzato.

Pertanto, hai due opzioni:

  • fare una spinta forzata, o
  • elimina il tag sul telecomando.

Quest'ultimo è possibile tramite git push2 anche se l'eliminazione del tag localmente e pushing non ha alcun effetto. Supponendo che il nome del telecomando sia origine il tag che si desidera eliminare sia dev:

git push origin :refs/tags/dev

Questo chiede al telecomando di eliminare il tag. La presenza o l'assenza del tag devnel repository locale è irrilevante; questo tipo di push, con come refspec, è una spinta a cancellazione pura.:remoteref

Il telecomando può o meno consentire l'eliminazione dei tag (a seconda di eventuali hook aggiuntivi aggiunti). Se consente l'eliminazione, il tag sparirà e un secondo git push --tags, quando si dispone di un devtag locale che punta a un oggetto repository tag commit o annotato, inviare il nuovo devtag. Sul telecomando, devora sarà un tag appena creato, quindi probabilmente il telecomando consentirà il push (di nuovo questo dipende da eventuali hook aggiuntivi aggiunti).

La spinta forzata è più semplice. Se si vuole essere sicuri di non aggiornamento niente altro che il tag, basta dire git pusha spingere solo quella refspec:

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

(nota: non è necessario --tagsse si sta esplicitamente spingendo solo una ref-spec tag).


1 Naturalmente, la ragione di questo hook integrato è di aiutare ad applicare il comportamento che altri utenti dello stesso repository remoto si aspettano: che i rami non vengano riavvolti e i tag non si spostino. Se spingi forzatamente, dovresti far sapere agli altri utenti che lo stai facendo, in modo che possano correggerlo. Nota che "i tag non si muovono affatto" è stato recentemente imposto da Git 1.8.2; le versioni precedenti avrebbero consentito al tag di "spostarsi in avanti" nel grafico di commit, proprio come i nomi dei rami. Vedi le note di rilascio di git 1.8.2 .

2 È banale se riesci ad accedere sul telecomando. Basta andare al repository Git lì ed eseguire git tag -d dev. Nota che in entrambi i casi, eliminando il tag sul telecomando o usando git pushper eliminarlo, c'è un periodo di tempo in cui chiunque accede al telecomando scoprirà che il devtag è mancante. (Continueranno ad avere il loro vecchio tag, se già lo hanno, e potrebbero persino riportare indietro il loro vecchio tag prima che tu possa spingere il nuovo.)


Succede solo nelle nuove versioni di git? Ho 1.7.9.5e non ho questo problema ...
Ionică Bizău,

2
Probalby: ho un vago ricordo di aver git push --tagscambiato automaticamente il tag nelle versioni precedenti di git, senza --force. Ho provato questo sotto 1.8.4 e, se necessario --force, o la tecnica di aggiornamento in due fasi.
Torek,

2
@John ツ: aggiornamento: è un nuovo comportamento a partire dalla 1.8.2, secondo le note di rilascio . Lo modificherò anche nella nota 1.
Torek,

Non so come sono arrivato a questa situazione, ma questo è stato cancellato e ricreato in un batter d'occhio.
RiggsFolly

4
come fai una spinta forzata se non sei un jedi?
Fonix,

54

In Mac SourceTree deseleziona solo la casella di controllo Push all tags :

inserisci qui la descrizione dell'immagine


3
hahahah uomo così semplice, stavo leggendo la risposta accettata e pensavo che l'avrei falsificata
MegaManX

10
Questo è solo per superarlo senza effettivamente risolvere il problema. Ciò non risolve la mancata corrispondenza del nome tag in remoto e locale.
amalBit,

1
funziona anche per la versione di Windows! grazie per averci salvato dalla lettura della risposta a lungo accettata che omette gli utenti sourcetree a cui non importa cosa sta succedendo nel prompt dei comandi :)
schlingel,

19

È abbastanza semplice se stai usando SourceTree .

inserisci qui la descrizione dell'immagine Fondamentalmente devi solo rimuovere e aggiungere nuovamente il tag in conflitto:

  1. Vai alla scheda Repository -> Tag -> Rimuovi tag
  2. Seleziona il nome del tag in conflitto
  3. Seleziona Rimuovi tag da tutti i telecomandi
  4. Premi Rimuovi
  5. Crea un nuovo tag con lo stesso nome per il commit corretto
  6. Assicurati di selezionare Invia tutti i tag quando invii le modifiche al telecomando

16

Se vuoi AGGIORNARE un tag, diciamolo1.0.0

  1. git checkout 1.0.0
  2. apporta le tue modifiche
  3. git ci -am 'modify some content'
  4. git tag -f 1.0.0
  5. elimina tag remoto su github: git push origin --delete 1.0.0
  6. git push origin 1.0.0

FATTO


12

Sembra che sia in ritardo su questo problema e / o abbia già ricevuto una risposta, ma ciò che si potrebbe fare è: (nel mio caso, avevo un solo tag localmente quindi .. ho eliminato il vecchio tag e lo ho ricodificato con :

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

Poi:

git push --tags -f

Ciò aggiornerà tutti i tag sul telecomando.

Potrebbe essere pericoloso! Utilizzare a proprio rischio.


1
Questo l'ha fatto per me! I tag erano solo localmente e non nel telecomando :)
pgarciacamou,

4

Il motivo per cui ti viene rifiutato è che il tag ha perso la sincronizzazione con la versione remota. Questo è lo stesso comportamento con i rami.

sincronizzare con il tag dal telecomando tramite git pull --rebase <repo_url> +refs/tags/<TAG>e dopo la sincronizzazione, è necessario gestire i conflitti . Se hai installato un diftool (es. Fusione) usalo git mergetool meldper sincronizzare il telecomando e mantenere le tue modifiche.

Il motivo per cui stai tirando con --rebase flag è che vuoi mettere il tuo lavoro in cima a quello remoto in modo da evitare altri conflitti.

Inoltre, ciò che non capisco è perché dovresti eliminare il devtag e ricrearlo ??? I tag vengono utilizzati per specificare le versioni del software o le pietre miliari. Esempio di tag git v0.1dev, v0.0.1alpha, v2.3-cr(cr - release candidate) e così via ..


Un altro modo per risolverlo è il problema a git refloge passare al momento in cui hai premuto il devtag sul telecomando. Copia l' id di commit e in git reset --mixed <commmit_id_from_reflog>questo modo sai che il tuo tag era sincronizzato con il telecomando nel momento in cui lo hai premuto e non sorgeranno conflitti.


Ad esempio, se si desidera taggare un commit attualmente in produzione. Dovresti quindi eliminare il vecchio tag di produzione da un commit specifico e creare e inviare un nuovo tag per il commit dopo la nuova versione di produzione.
Ville Miekk-oja,

2

In Windows SourceTree, deselezionare Push all tags to remotes.

inserisci qui la descrizione dell'immagine


0

Alcune buone risposte qui. Soprattutto quello di @torek . Ho pensato di aggiungere questa soluzione con una piccola spiegazione per chi ha fretta.

Per riassumere, ciò che accade è che quando si sposta un tag localmente, il tag cambia da un valore di commit non Null a un valore diverso. Tuttavia, poiché git (come comportamento predefinito) non consente la modifica di tag remoti non Null, non è possibile inviare la modifica.

La soluzione è eliminare il tag (e selezionare Rimuovi tutti i telecomandi). Quindi crea lo stesso tag e premi.

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.