Changer la date de la balise git (ou de la version GitHub en fonction de celle-ci)

95

J'ajoute des versions à mes projets sur GitHub en ajoutant des balises à divers commits dans la branche principale.

Dans l'un de mes projets, je n'ai pas ajouté les balises aux commits dans l'ordre chronologique. (J'ai trouvé des commits évidents et les ai étiquetés, puis j'ai trouvé des commits moins évidents et plus anciens et les ai étiquetés.)

Maintenant GitHub montre v1.0.1 que le courant, avec v0.7.0 précédentes, et v1.1.2 précédentes qui .

Il semble utiliser la date de création d'une balise comme date de publication au lieu de la validation qui est balisée. Comment puis-je modifier mes tags pour que leurs dates soient identiques à celles du commit qu'ils balisent?

mapping des versions et des dates entre gitk et GitHub

Phrogz
la source

Réponses:

118

AVERTISSEMENT: cela ne conservera pas les messages de balise pour les balises annotées.

Résumé

Pour chaque balise à modifier:

  1. Remontez dans le temps jusqu'au commit représentant le tag
  2. Supprimer le tag (localement et à distance)
    • Cela transformera votre "Release" sur GitHub en un brouillon que vous pourrez supprimer ultérieurement.
  3. Ajoutez à nouveau la balise du même nom en utilisant un appel magique qui définit sa date sur la date de la validation.
  4. Poussez les nouvelles balises avec des dates fixes vers GitHub.
  5. Accédez à GitHub, supprimez toutes les versions actuellement brouillon et recréez de nouvelles versions à partir des nouvelles balises

Dans du code:

# 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

Détails

Selon Comment étiqueter dans Git :

Si vous oubliez de marquer une version ou une modification de version, vous pouvez toujours la marquer rétroactivement comme ceci:

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

Et bien que cela soit parfaitement utilisable, cela a pour effet de mettre vos balises dans l'ordre chronologique, ce qui peut se visser avec des systèmes de construction qui recherchent la «dernière» balise. Mais n'ayez pas peur. Linus a pensé à tout:

# 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"

Cependant, si vous avez déjà ajouté la balise, vous ne pouvez pas utiliser ce qui précède avec git tag -f existingtagsinon git se plaindra lorsque vous essayez de fusionner:

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

Au lieu de cela, vous devez supprimer la balise localement:

git tag -d 1.0.1

Poussez cette suppression à distance:

git push origin :refs/tags/1.0.1

Sur GitHub, rechargez les versions (la version a maintenant été marquée comme "Brouillon") et supprimez le brouillon.

Maintenant, ajoutez la balise antidatée en fonction des instructions ci-dessus, et enfin poussez la balise résultante vers GitHub:

git push --tags

puis allez et ajoutez à nouveau les informations de version de GitHub.

Phrogz
la source
2
Voici un script bash qui supprime et rajoute chaque balise dans un 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
dépôt
11
Vous devriez pouvoir faire toutes ces choses sans vérifier la balise. Voici une modification de votre one-liner qui a été beaucoup plus rapide pour moi: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
l'utilisation git tag -afrend -dinutile et vous restez local afin que vous puissiez vérifier que tout va bien - alors vous pouvezgit push --tags -f
Mr_and_Mrs_D
3
@Mr_and_Mrs_D Bonne suggestion et un bon moyen de limiter cette opération à une seule pression. Dans cet esprit, je pense que le one-liner résultant (non testé) seraitgit 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
Cela fonctionne dans git shell pour PowerShell, mais vous devez définir la variable d'environnement différemment et le faire sur deux lignes: $env:GIT_COMMITTER_DATE="Thu Nov 11 12:21:57 2010 -0800"etgit tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"
roncli
18

Voici un aperçu basé sur certains des commentaires de l'autre réponse:

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

ATTENTION: cela nuke vos balises amont et ne conservera pas les messages pour les balises annotées! Assurez-vous que vous savez ce que vous faites et NE FAITES PAS cela pour un référentiel public !!!

Pour le décomposer ...

# 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

Merci à @Mr_and_Mrs_D pour la suggestion d'utiliser un seul push.

vmrob
la source
3

Sur la base des autres réponses, voici une manière qui va préserver la première ligne du message d'étiquette

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

Le bit responsable de la conservation des messages est:

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

head -n1prendra la première ligne de l'ancien message de validation. Vous pouvez le modifier en -n2ou -n3etc pour obtenir deux ou trois lignes à la place.

Si vous souhaitez modifier la date / l'heure pour une seule balise, voici comment vous pouvez décomposer le one-liner pour le faire dans votre 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

Références:

weiji14
la source
C'est génial, merci. Dans les commandes pour changer une seule balise, cependant, il y a un -sdrapeau qui n'est pas présent dans le one-liner, donc j'obtenais error: gpg failed to sign the dataparce que je n'ai pas configuré de signature pour git. Cette erreur m'a un peu dérangé.
CHM