Come posso spostare un tag su un ramo git in un commit diverso?


858

Ho creato un tag sul ramo principale chiamato in v0.1questo modo:

git tag -a v0.1

Ma poi ho capito che c'erano ancora alcune modifiche che dovevo unire in master per la versione 0.1, quindi l'ho fatto. Ma ora il mio v0.1tag è bloccato (per invocare l'analogia post-it note) il commit errato. Voglio che sia bloccato sul commit più recente sul master, ma invece è bloccato sul secondo commit più recente sul master.

Come posso spostarlo sul commit più recente sul master?

Risposte:


1200

Usa l' -fopzione per git tag:

-f
--force

    Replace an existing tag with the given name (instead of failing)

Probabilmente si desidera utilizzare -fcongiuntamente a -aper forzare la creazione di un tag con annotazioni anziché non con annotazioni.

Esempio

  1. Elimina il tag su qualsiasi telecomando prima di premere

    git push origin :refs/tags/<tagname>
    
  2. Sostituisci il tag per fare riferimento al commit più recente

    git tag -fa <tagname>
    
  3. Spingere il tag sull'origine remota

    git push origin master --tags
    

90
Potrebbe essere una buona idea eliminare il tag su qualsiasi telecomando prima di premere anche, facendo questo: git push origin :refs/tag/<tagname>e poi fai git tag -fa <tagname>e poi git push origin master --tags. Altrimenti potresti finire con cose strane nell'elenco dei riferimenti sul telecomando con i caratteri ^ e {} aggiunti. Grazie a Dan su codebasehq.com per averlo segnalato.
settembre

47
@eedeep: correzione minore - invece :refs/tag/<tagname>che dovrebbe essere :refs/tags/<tagname>.
Ben Hocking,

8
Funziona solo se non hai rimosso il codice dal tuo computer. Se hai, la risposta migliore è "ci sono molti numeri nel mondo" in quanto probabilmente non vale la seccatura.
Chris Huang-Leaver,

33
Se hai già inviato il tag, puoi comunque aggiornare il tag remoto con un push forzatogit push -f origin <tagname>
rc_luke,

11
Ciò che non è menzionato qui e nei documenti è che questo effettivamente sposta il messaggio tag, se non viene dato alcun nuovo messaggio.
Twonky,

259

Più precisamente, devi forzare l'aggiunta del tag, quindi spingere con l'opzione --tags e -f:

git tag -f -a <tagname>
git push -f --tags

171

Per riassumere se il tuo telecomando viene chiamato origine stai lavorando su una masterfiliale:

git tag -d <tagname>
git push origin :refs/tags/<tagname>
git tag <tagname> <commitId>
git push origin <tagname>
  • La riga 1 rimuove il tag in env locale.
  • La riga 2 rimuove il tag in ambiente remoto.
  • La riga 3 aggiunge il tag a diversi commit
  • La linea 4 invia la modifica al telecomando

Puoi anche scambiare la linea 4 per git push origin --tagsinviare tutte le modifiche con i tag delle modifiche locali.

Basandomi su @ stuart-golodetz, @ greg-hewgill, @eedeep, @ ben-hocking risposte, commenti sotto le loro risposte e commenti NateS sotto la mia risposta.


87

Eliminalo con git tag -d <tagname>e poi ricrealo sul commit corretto.


3
@eedeep: Penso che la risposta di Greg sia effettivamente migliore qui per essere onesti.
Stuart Golodetz,

Mantienilo semplice. Eliminalo, fai quello che hai fatto prima.
Ooolala,

1
Questa dovrebbe essere la risposta accettata, per la sua semplicità. Inoltre non usa -f forza eccessivamente.
chinnychinchin,

48

Cerco di evitare alcune cose quando uso Git.

  1. Utilizzo della conoscenza degli interni, ad esempio refs / tag. Cerco di usare solo i comandi Git documentati ed evito di usare cose che richiedono la conoscenza dei contenuti interni della directory .git. (Vale a dire, tratto Git come un utente Git e non uno sviluppatore Git.)

  2. L'uso della forza quando non richiesto.

  3. Esagerare le cose. (Premendo un ramo e / o molti tag, per ottenere un tag dove lo voglio.)

Quindi ecco la mia soluzione non violenta per la modifica di un tag, sia localmente che da remoto, senza la conoscenza degli interni di Git.

Lo uso quando una correzione software alla fine ha un problema e deve essere aggiornata / ripubblicata.

git tag -d fix123                # delete the old local tag
git push github :fix123          # delete the old remote tag (use for each affected remote)
git tag fix123 790a621265        # create a new local tag
git push github fix123           # push new tag to remote    (use for each affected remote)

githubè un nome remoto di esempio, fix123è un nome tag di esempio e 790a621265un commit di esempio.


26

Lascio qui solo un'altra forma di questo comando che si adatta alle mie esigenze.
C'era un tag v0.0.1.2che volevo spostare.

$ git tag -f v0.0.1.2 63eff6a

Updated tag 'v0.0.1.2' (was 8078562)

E poi:

$ git push --tags --force

bene, grazie, 2 comandi chiari e semplici
Sérgio

10

Un altro modo:

Sposta il tag nel repository remoto (sostituisci HEAD con qualsiasi altro se necessario).

$ git push --force origin HEAD:refs/tags/v0.0.1.2

Recupera modifiche.

$ git fetch --tags

Questo è più "transazionale" rispetto alle altre risposte.
Justin M. Keyes,

9

Alias ​​per spostare un tag in un commit diverso.

Nel vostro campione, per spostare impegnarsi con e2ea1639 hash fare: git tagm v0.1 e2ea1639.

Per i tag push, utilizzare git tagmp v0.1 e2ea1639.

Entrambi gli alias mantengono la data e il messaggio originali. Se usi git tag -dhai perso il messaggio originale.

Salvali sul tuo .gitconfigfile

# Return date of tag. (To use in another alias)
tag-date = "!git show $1 | awk '{ if ($1 == \"Date:\") { print substr($0, index($0,$3)) }}' | tail -2 | head -1 #"

# Show tag message
tag-message = "!git show $1 | awk -v capture=0 '{ if(capture) message=message\"\\n\"$0}; BEGIN {message=\"\"}; { if ($1 == \"Date:\" && length(message)==0 ) {capture=1}; if ($1 == \"commit\" ) {capture=0}  }; END { print message }' | sed '$ d' | cat -s #"

### Move tag. Use: git tagm <tagname> <newcommit> 
tagm = "!GIT_TAG_MESSAGE=$(git tag-message $1) && GIT_COMMITTER_DATE=$(git tag-date $1) && git tag-message $1 && git tag -d $1 && git tag -a $1 $2 -m \"$GIT_TAG_MESSAGE\" #"

### Move pushed tag. Use: git tagmp <tagname> <newcommit> 
tagmp = "!git tagm $1 $2 && git push --delete origin $1 && git push origin $1 #"

1

Se vuoi spostare un tag annotato, cambiando solo il commit mirato ma preservando il messaggio di annotazione e altri metadati usa:

moveTag() {
  local tagName=$1
  # Support passing branch/tag names (not just full commit hashes)
  local newTarget=$(git rev-parse $2^{commit})

  git cat-file -p refs/tags/$tagName | 
    sed "1 s/^object .*$/object $newTarget/g" | 
    git hash-object -w --stdin -t tag | 
    xargs -I {} git update-ref refs/tags/$tagName {}
}

utilizzo: moveTag <tag-to-move> <target>

La funzione sopra è stata sviluppata facendo riferimento a teerapap / git-move-annotated-tag.sh .


1
Sembra che non sia più necessario: git tag -f -a my_tagconserva già il messaggio di un messaggio precedente (con git versione 2.11.0).
Matthijs Kooijman,
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.