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 fetch
e l'aggiornamento è il comportamento predefinito per i client in esecuzione git fetch --tags
.
(Segue la risposta originale.)
Quando chiedi di git push --tags
inviare 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-sha1
valore è 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 push
passo 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 push
2 anche se l'eliminazione del tag localmente e push
ing non ha alcun effetto. Supponendo che il nome del telecomando sia origin
e 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 dev
nel 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 dev
tag locale che punta a un oggetto repository tag commit o annotato, inviare il nuovo dev
tag. Sul telecomando, dev
ora 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 push
a spingere solo quella refspec:
git push --force origin refs/tags/dev:refs/tags/dev
(nota: non è necessario --tags
se 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 push
per eliminarlo, c'è un periodo di tempo in cui chiunque accede al telecomando scoprirà che il dev
tag è 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.)