Ändern Sie das Datum des Git-Tags (oder der darauf basierenden GitHub-Version).

95

Ich füge Releases zu meinen Projekten auf GitHub hinzu, indem ich Tags zu verschiedenen Commits im Hauptzweig hinzufüge.

In einem meiner Projekte habe ich die Tags nicht in chronologischer Reihenfolge zu den Commits hinzugefügt. (Ich fand offensichtliche Commits und markierte sie, und dann fand ich weniger offensichtliche, ältere Commits und markierte sie.)

Nun zeigt GitHub v1.0.1 als Strom mit v0.7.0 vorausgehenden und v1.1.2 vorhergehenden daß .

Es scheint, dass das Datum bei der Erstellung eines Tags als Veröffentlichungsdatum anstelle des Commits verwendet wird, das markiert wird. Wie kann ich meine Tags so bearbeiten, dass ihre Daten mit dem Commit übereinstimmen, das sie markieren?

Zuordnung von Releases und Daten zwischen gitk und GitHub

Phrogz
quelle

Antworten:

117

WARNUNG: Hiermit werden keine Tag-Nachrichten für kommentierte Tags beibehalten.

Zusammenfassung

Für jedes Tag, das geändert werden muss:

  1. Gehen Sie zurück in die Zeit des Commits, das das Tag darstellt
  2. Löschen Sie das Tag (lokal und remote)
    • Dadurch wird Ihre "Veröffentlichung" auf GitHub in einen Entwurf umgewandelt, den Sie später löschen können.
  3. Fügen Sie das gleichnamige Tag erneut hinzu, indem Sie einen magischen Aufruf verwenden, dessen Datum auf das Datum des Commits festgelegt wird.
  4. Schieben Sie die neuen Tags mit festen Daten zurück auf GitHub.
  5. Gehen Sie zu GitHub, löschen Sie alle jetzt entworfenen Releases und erstellen Sie neue Releases aus den neuen Tags neu

In 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

Einzelheiten

Laut How to Tag in Git :

Wenn Sie vergessen haben, ein Release oder einen Versions-Bump zu markieren, können Sie es jederzeit rückwirkend wie folgt markieren:

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

Und obwohl dies perfekt verwendbar ist, hat es den Effekt, dass Ihre Tags in chronologischer Reihenfolge angeordnet werden, was mit Build-Systemen, die nach dem "neuesten" Tag suchen, verschraubt werden kann. Aber keine Angst. Linus dachte an alles:

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

Wenn Sie das Tag jedoch bereits hinzugefügt haben, können Sie das oben genannte nicht mit verwenden git tag -f existingtag, da sich git sonst beim Zusammenführen beschwert:

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.

Stattdessen müssen Sie das Tag lokal entfernen:

git tag -d 1.0.1

Drücken Sie diese Löschung aus der Ferne:

git push origin :refs/tags/1.0.1

Laden Sie auf GitHub Releases neu - die Version wurde jetzt als "Entwurf" markiert - und entfernen Sie den Entwurf.

Fügen Sie nun das rückdatierte Tag basierend auf den obigen Anweisungen hinzu und senden Sie das resultierende Tag schließlich an GitHub:

git push --tags

und fügen Sie dann die GitHub-Release-Informationen erneut hinzu.

Phrogz
quelle
2
Hier ist ein Bash-Skript, das jedes Tag in einem Git-Repo entfernt und wieder hinzufügt: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
Sie sollten in der Lage sein, all diese Dinge zu tun, ohne das Tag auszuchecken. Hier ist eine Modifikation Ihres 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
Einzeilers, die
2
Verwenden von git tag -afmacht -dunnötig und Sie bleiben lokal, damit Sie überprüfen können, ob alles in Ordnung ist - dann können Siegit push --tags -f
Mr_and_Mrs_D
3
@Mr_and_Mrs_D Guter Vorschlag und eine gute Möglichkeit, diesen Vorgang auf einen Push zu beschränken. In diesem Sinne denke ich, dass der resultierende (ungetestete) Einzeilergit 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
Einzeiler sein vmrob
2
Dies funktioniert in Git Shell für PowerShell, aber Sie müssen die Umgebungsvariable anders einstellen und dies in zwei Zeilen tun: $env:GIT_COMMITTER_DATE="Thu Nov 11 12:21:57 2010 -0800"undgit tag -a 0.9.33 -m"Retroactively tagging version 0.9.33"
Roncli
18

Hier ist ein Einzeiler basierend auf einigen Kommentaren in der anderen Antwort:

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

WARNUNG: Dadurch werden Ihre Upstream-Tags zerstört und Nachrichten für kommentierte Tags werden nicht gespeichert! Stellen Sie sicher, dass Sie wissen, was Sie tun, und tun Sie dies definitiv nicht für ein öffentliches Repository !!!

Um es zu brechen ...

# 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

Vielen Dank an @Mr_and_Mrs_D für den Vorschlag, einen einzelnen Push zu verwenden.

vmrob
quelle
3

Aufbauend auf den anderen Antworten, hier ist ein Weg, wird die erste Zeile der Tag - Nachricht erhalten

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

Das Bit, das für die Aufbewahrung der Nachrichten verantwortlich ist, ist:

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

head -n1nimmt die erste Zeile der alten Festschreibungsnachricht. Sie können es in -n2oder ändern-n3 usw. , um stattdessen zwei oder drei Zeilen zu erhalten.

Wenn Sie Datum und Uhrzeit für nur ein Tag ändern möchten, können Sie den Einzeiler folgendermaßen aufteilen, um dies in Ihrer Bash-Shell zu tun:

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

Verweise:

weiji14
quelle
Das ist großartig, danke. In den Befehlen zum Ändern eines einzelnen Tags befindet sich jedoch ein -sFlag, das im Einzeiler nicht vorhanden ist. Ich habe es also erhalten, error: gpg failed to sign the dataweil ich keine Signatur für git eingerichtet habe. Dieser Fehler warf mich ein bisschen ab.
wch