Modifica la data del tag git (o la versione GitHub basata su di esso)


95

Sto aggiungendo le versioni ai miei progetti su GitHub aggiungendo tag a vari commit nel ramo principale.

In uno dei miei progetti non ho aggiunto i tag ai commit in ordine cronologico. (Ho trovato commit evidenti e li ho etichettati, quindi ho trovato commit meno ovvi, meno recenti e li ho contrassegnati.)

Ora GitHub mostra la v1.0.1 come corrente, con la v0.7.0 che la precede e la v1.1.2 che la precede .

Sembra utilizzare la data sulla creazione di un tag come data di rilascio invece del commit che viene taggato. Come posso modificare i miei tag in modo che le loro date siano le stesse del commit che stanno etichettando?

mappatura delle versioni e delle date tra gitk e GitHub

Risposte:


118

AVVISO: questo non conserverà i messaggi di tag per i tag annotati.

Sommario

Per ogni tag che deve essere modificato:

  1. Torna indietro nel tempo al commit che rappresenta il tag
  2. Elimina il tag (in locale e in remoto)
    • Questo trasformerà il tuo "rilascio" su GitHub in una bozza che potrai successivamente eliminare.
  3. Riaggiungi il tag con lo stesso nome usando una chiamata magica che imposta la sua data alla data del commit.
  4. Esegui il push dei nuovi tag con date fisse su GitHub.
  5. Vai su GitHub, elimina tutte le versioni in bozza e ricrea le nuove versioni dai nuovi tag

In codice:

# Fixing tag named '1.0.1'
git checkout 1.0.1               # Go to the associated commit
git tag -d 1.0.1                 # Locally delete the tag
git push origin :refs/tags/1.0.1 # Push this deletion up to GitHub

# Create the tag, with a date derived from the current head
GIT_COMMITTER_DATE="$(git show --format=%aD | head -1)" git tag -a 1.0.1 -m"v1.0.1"

git push --tags                  # Send the fixed tags to GitHub

Dettagli

Secondo How to Tag in Git :

Se dimentichi di taggare una release o un bump di versione, puoi sempre taggarlo retroattivamente in questo modo:

git checkout SHA1_OF_PAST_COMMIT
git tag -m"Retroactively tagging version 1.5" v1.5

E sebbene sia perfettamente utilizzabile, ha l'effetto di mettere i tuoi tag fuori ordine cronologico, il che può rovinare i sistemi di build che cercano il tag "più recente". Ma non aver paura. Linus ha pensato a tutto:

# This moves you to the point in history where the commit exists
git checkout SHA1_OF_PAST_COMMIT

# This command gives you the datetime of the commit you're standing on
git show --format=%aD  | head -1

# And this temporarily sets git tag's clock back to the date you copy/pasted in from above
GIT_COMMITTER_DATE="Thu Nov 11 12:21:57 2010 -0800" git tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"

# Combining the two...
GIT_COMMITTER_DATE="$(git show --format=%aD  | head -1)" git tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"

Tuttavia, se hai già aggiunto il tag, non puoi usare quanto sopra con git tag -f existingtagaltrimenti git si lamenterà quando proverai a unire:

Rammy:docubot phrogz$ git push --tags
To git@github.com:Phrogz/docubot.git
 ! [rejected]        1.0.1 -> 1.0.1 (already exists)
error: failed to push some refs to 'git@github.com:Phrogz/docubot.git'
hint: Updates were rejected because the tag already exists in the remote.

Invece, devi rimuovere il tag localmente:

git tag -d 1.0.1

Spingi l'eliminazione da remoto:

git push origin :refs/tags/1.0.1

Su GitHub, ricarica le versioni (la versione ora è stata contrassegnata come "Bozza") e rimuovi la bozza.

Ora aggiungi il tag retrodatato in base alle istruzioni sopra e infine invia il tag risultante a GitHub:

git push --tags

quindi vai e aggiungi nuovamente le informazioni sulla versione di GitHub.


2
Ecco uno script bash che rimuove e aggiunge di nuovo ogni tag in un repository git:git tag -l | while read -r tag; do `git checkout $tag && git tag -d $tag && git push origin :refs/tags/$tag && GIT_COMMITTER_DATE="$(git show --format=%aD | head -1)" git tag -a $tag -m"$tag"`; done; git push --tags
Phrogz

11
Dovresti essere in grado di fare tutte queste cose senza controllare il tag. Ecco una modifica della tua battuta che è stata molto più veloce per me:git tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) && git tag -d $tag && git push origin :refs/tags/$tag && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a $tag -m"$tag" $COMMIT_HASH ; done && git push --tags
vmrob

2
utilizzando git tag -afmarche -dnon necessarie e rimani locale in modo da poter controllare che tutto git push --tags -f
vada

3
@Mr_and_Mrs_D Buon suggerimento e un buon modo per limitare questa operazione a una sola spinta. Con questo in mente, penso che la battuta risultante (non testata) sarebbegit tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$tag" $COMMIT_HASH ; done && git push --tags --force
vmrob

2
Funziona in git shell per PowerShell, ma devi impostare la variabile d'ambiente in modo diverso e farlo su due righe: $env:GIT_COMMITTER_DATE="Thu Nov 11 12:21:57 2010 -0800"egit tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"
roncli

18

Ecco una battuta basata su alcuni dei commenti nell'altra risposta:

git tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$tag" $COMMIT_HASH ; done && git push --tags --force

ATTENZIONE: questo distruggerà i tuoi tag upstream e non conserverà i messaggi per i tag annotati! Assicurati di sapere cosa stai facendo e SICURAMENTE non farlo per un repository pubblico !!!

Per scomporlo ...

# Loop over tags
git tag -l | while read -r tag
do

    # get the commit hash of the current tag
    COMMIT_HASH=$(git rev-list -1 $tag)

    # get the commit date of the tag and create a new tag using
    # the tag's name and message. By specifying the environment
    # environment variable GIT_COMMITTER_DATE before this is
    # run, we override the default tag date. Note that if you
    # specify the variable on a different line, it will apply to
    # the current environment. This isn't desired as probably
    # don't want your future tags to also have that past date.
    # Of course, when you close your shell, the variable will no
    # longer persist.
    GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$tag" $COMMIT_HASH


done

# Force push tags and overwrite ones on the server with the same name
git push --tags --force

Grazie a @Mr_and_Mrs_D per il suggerimento di utilizzare una singola spinta.


3

Sulla base delle altre risposte, ecco un modo che sarà preservare la prima riga del messaggio tag

git tag -l | while read -r tag ; do COMMIT_HASH=$(git rev-list -1 $tag) COMMIT_MSG=$(git tag -l --format='%(contents)' $tag | head -n1) && GIT_COMMITTER_DATE="$(git show $COMMIT_HASH --format=%aD | head -1)" git tag -a -f $tag -m"$COMMIT_MSG" $COMMIT_HASH ; done
git tag -l -n1           #check by listing all tags with first line of message
git push --tags --force  #push edited tags up to remote

Il bit responsabile della conservazione dei messaggi è:

COMMIT_MSG=$(git tag -l --format='%(contents)' $tag | head -n1)

head -n1prenderà la prima riga del vecchio messaggio di commit. Puoi modificarlo in -n2o -n3ecc per ottenere invece due o tre righe.

Se vuoi cambiare la data / ora per un solo tag, ecco come puoi scomporre la riga per farlo nella tua shell bash:

tag=v0.1.0
COMMIT_HASH=$(git rev-list -1 $tag)
COMMIT_MSG=$(git tag -l --format='%(contents)' $tag | head -n1)
COMMIT_DATE=$(git show $COMMIT_HASH --format=%aD | head -1)
GIT_COMMITTER_DATE=$COMMIT_DATE git tag -s -a -f $tag -m"$COMMIT_MSG" $COMMIT_HASH

Riferimenti:


È fantastico, grazie. Nei comandi per cambiare un singolo tag, però, c'è un -sflag che non è presente nell'unica riga, quindi stavo ottenendo error: gpg failed to sign the dataperché non ho impostato la firma per git. Quell'errore mi ha sconvolto per un po '.
WCH
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.