Wie bearbeite ich eine vorhandene Tag-Nachricht in Git?

225

Wir haben mehrere kommentierte Tags in unserem Git-Repository. Die älteren Tags enthalten gefälschte Nachrichten, die wir aktualisieren möchten, um sie in unserem neuen Stil zu erhalten.

% git tag -n1
v1.0 message
v1.1 message
v1.2 message
v2.0 Version 2.0 built on 15 October 2011.

In diesem Beispiel möchten wir, dass v1.x-Nachrichten wie die v2.0-Nachricht aussehen. Weiß jemand, wie wir das machen würden?

jared
quelle
2
Hinweis: Mit Git 2.17 (Q2 2018) git tag -m "A message" --edit v1.0würde ein einfaches ausreichen. Siehe meine Antwort unten
VonC
Verwandte: Wie benennt man ein Git-Tag um?
Stevoisiak
@VonC Versuchte es und erhielt fatal: tag 'v6.6.2' already existsmit 2.17.0.
Josh Habdas
1
Sie können das vorherige Tag jederzeit löschen und erneut ausführen.
RoadRunner

Antworten:

264

git tag <tag name> <tag name>^{} -f -m "<new message>"

Dadurch wird ein neues Tag mit demselben Namen erstellt (indem das Original überschrieben wird).

Andy
quelle
7
Behält dies das Datum des ursprünglichen Tags bei?
James M. Greene
16
Antwort auf meine eigene Kommentarfrage: Ja, das Datum ändert sich. :(
James M. Greene
10
Siehe den Abschnitt "On Backdating Tags" in git tag --help.
Dahlbyk
6
Es sollte auch beachtet werden, dass Sie auch mehrere Nachrichten anhängen können (sie werden durch eine neue Zeile getrennt - auf GitHub)git tag <tag name> <tag name> -f -m "<new message>" -m "<new message>" -m "<new message>"
Blair McMillan
5
@ ChrisMorley schaut auf meine Antwort unten stackoverflow.com/a/23532519/603949 - kurz, verwenden <tag name>^{}Sie , wenn Sie dieold tag
Sungam
87

Um eine komplexe Nachricht zu aktualisieren, geben Sie einfach die Option für kommentierte Tags mit -aoder die Option für signierte Tags mit an -s:

git tag <tag name> <tag name>^{} -f -a

Dadurch wird ein Editor mit dem Inhalt Ihrer alten Tag-Nachricht geöffnet .

Eric Hu
quelle
39

git tag <tag name> <tag name>^{} -f -a

Dies ist eine Verbesserung: Ohne ^{}wird ein neues Tag-Objekt erstellt, das auf das alte Tag-Objekt verweist, wobei beide denselben Tag-Namen haben.

<tag name>^{} löst das Tag / die Referenz auf, bis der erste Commit-Hash gefunden wird.

Sungam
quelle
4
@BrentFoust, das funktioniert nur, wenn Ihr Kopf beim getaggten Commit ist usage: git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]
Sungam
33

TL; DR

Sie können dies tun, indem Sie Ihr Tag löschen und neu erstellen, während Sie Datum und Autor fälschen:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

Ganze Geschichte:

Aufbauend auf Sungrams Antwort (ursprünglich als Bearbeitung vorgeschlagen):

1. Akzeptierte Antwort

Dies ist eine Verbesserung gegenüber den Antworten von Andy und Eric Hu . Ihre Antworten erstellen ein neues Tag-Objekt, das auf das alte Tag-Objekt verweist, und beide haben denselben Namen.

Betrachten Sie zur Veranschaulichung Folgendes:

> git tag tag1 tag1 -f -a  # accepted answer
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
260ab7928d986472895b8c55e54569b3f3cb9517 tag1
a5797673f610914a45ef7ac051e3ee831a6e7c25 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Original description]

[tagged commit details]

2. Sungrams Verbesserung

Verwenden Sie stattdessen <tag name>^{}als zweites Argument von git tagwill alle vorherigen Tags mit demselben Namen.

Betrachten Sie die Fortsetzung der vorherigen Terminalsitzung:

> git tag tag1 tag1^{} -f -a  # suggested improvement
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
75f02acacfd7d91d55b5bcfdfb1f00aebeed15e3 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17 

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

[tagged commit details]

3. Speichern Sie das Datum

Wenn Sie das Datum des ursprünglichen Tags als Datum des aktualisierten Tags beibehalten möchten, verwenden Sie eine awk (oder ähnliche) Magie oder fügen Sie stattdessen einfach das gewünschte Datum ein. Das Folgende ist ein Ersatz für das zweite Beispiel (andernfalls würde das ursprüngliche Datum durch Überschreiben verloren gehen):

> GIT_COMMITTER_DATE="$(git show tag1 |                              # get info about the tag cascade including the date original of the original tag
> awk '{
>     if ($1 == "Date:") {
>         print substr($0, index($0,$3))
>     }
> }' |                                                               # extract all the dates from the info
> tail -2 | head -1)"                                               `# get the second to last date, as the last one is the commit date` \
> git tag tag1 tag1^{} -a -f                                         # finally, update the tag message, but save the date of the old one
>
> git rev-list --objects -g --no-walk --all
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
e18c178f2a548b37799b100ab90ca785af1fede0 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17
> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Updated description]

[tagged commit details]

Verweise:

4. DIY

Alternativ zum Aktualisieren der Tags können Sie sie einfach löschen und erneut erstellen. Wie sich herausstellt, fügt das Aktualisieren nur ein neues Tag hinzu und verweist auf das alte, oder löscht alternativ einfach implizit das alte und erstellt ein neues, das ohnehin auf dasselbe Commit verweist.

Sie können dies erreichen, indem Sie Folgendes ausgeben:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

Hier [optional]ist ein optionales Feld; <required>Ist ein Pflichtfeld. Natürlich können Sie nach dem git tagBefehl beliebige Flags hinzufügen .

stanm
quelle
3
Vielen Dank für den Hinweis, dass "Ihre Antworten ein neues Tag-Objekt erstellen"!
cwhsu
Zitat Andreas Schwab : The tagger is controlled by the committer info. (...) GIT_COMMITTER_{NAME,EMAIL}. A tagger isn't really an author.
Ivan Vučica
11

@Andys Lösung

git tag <tag-name> <tag-name> -f -a

ist falsch . Danach mit

git show

Befehl sehen wir Stapel-Tags mit dem gleichen Namen.

Beim Festschreiben wird ein neues Tag mit demselben Tag-Namen und derselben neuen Nachricht hinzugefügt <tag-name>. Das alte Tag wird jedoch nicht entfernt. Es ist ein Sonderfall dieses Befehls:

git tag [<commit> | <old-tag>] <tag-name>

Aber genauso <old-tag>ist es mit <tag-name>.


Die richtige Lösung ist einfach, nur das Update-Tag ist in Ordnung.

git tag <tag-name> -f -a

Denken Sie daran, nur EIN hier.

Wenn wir das Tag ändern möchten, was nicht der Fall ist HEAD, benötigen wir ein zusätzliches <commit>Argument.

git tag <commit> <tag-name> -f -a
liuyang1
quelle
JA! Du hast recht. Danke, dass du darauf hingewiesen hast. Nachdem ich das mit Anmerkungen versehene Tag einige Male neu geschrieben hatte, überprüfte ich mein Tag mit git show <tag>und sehe alle vorherigen Ausgaben.
Manoel Vilela
Das Problem ist: Wenn ich ein Tag aktualisieren muss, das nicht vorhanden HEADist <commit>, ist das geöffnete Tag leer. Ich habe erwartet, dass das alte Tag nur bearbeitet wird. Gibt es einen Weg?
Manoel Vilela
Bitte beachten Sie, dass Andys Lösung seit Ihrer Antwort aktualisiert wurde. Vielleicht wäre es schön, Ihre Antwort mit einer Nachricht zu beginnen, die besagt, dass sie behoben wurde? Könnte es auch sein, dass Ihr Befehl git tag <commit> <tag-name> -f -a<commit> und <tag-name> umgekehrt hat? Im Vergleich mit anderen Antworten und den Dokumenten sieht es so aus, aber ich bin kein Experte.
Jacob Akkerboom
7

Wir möchten, dass v1.x-Nachrichten wie die v2.0-Nachricht aussehen

Mit Git 2.17 (Q2 2018) gibt es eine Alternative zum Erstellen eines neuen Tags mit git tag <tag name> <tag name> -f -m "<new message>", da " git tag" eine explizite " --edit" Option gelernt wurde , mit der die über " -m" und " -F" übermittelte Nachricht weiter bearbeitet werden kann.

Siehe Commit 9eed6e4 (06. Februar 2018) von Nicolas Morey-Chaisemartin ( nmorey) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 05d290e , 06. März 2018)

tag: --editOption hinzufügen

Fügen Sie eine --editOption hinzu, mit der Sie die von -moder bereitgestellten Nachrichten auf -Fdie gleiche Weise git commit --editändern können.

VonC
quelle
4
Könnten Sie bitte ein zusammenhängendes Beispiel geben, --editdas sich an das OP richtet?
Josh Habdas
@JoshHabdas tatsächlich müssen Sie die Option -f hinzufügen: --edit ermöglicht nur die weitere Bearbeitung der Nachricht.
VonC
Vielen Dank. Wenn also auch ein -fFlag hinzugefügt --editwird, wird die Nachricht bearbeitet und der Zeitstempel geändert, oder?
Josh Habdas
@ JoshHabdas Das ist die Idee, ja.
VonC
4

Sie müssen erneut mit dem -fForce-Flag markieren .

git tag v1.0 -f -m "actual message"
Manojlds
quelle
3
Diese Lösung setzt voraus, dass der aktuelle Git-Kopf die Version 1.0 hat. Dies kann zu Problemen führen, wenn dies nicht der Fall ist, da die mit Version 1.0 verknüpfte Revision geändert wird. Andys Lösung vermeidet diese Gefahr.
Eric O Lebigot
4

Mit den obigen Antworten ist dies mein Alias ​​Einzeiler für .gitconfig. Ersetzt das vorhandene Tag und behält das Festschreibungsdatum bei.

[alias]
    tm = "!sh -c 'f() { export GIT_COMMITTER_DATE=$(git log -1 --format=%ci $0); git tag -f -a $0 $0^{}; }; f '"

Verbesserungen?

h0tw1r3
quelle
1
tag-amend = "!sh -c 'f() { name=$(git log -1 --format=%an $0); email=$(git log -1 --format=%ae $0); date=$(git log -1 --format=%ci $0); GIT_AUTHOR_NAME=\"${name}\" GIT_COMMITTER _NAME=\"${name}\" GIT_AUTHOR_EMAIL=\"${email}\" GIT_COMMITTER_EMAIL=\"${email}\" GIT_AUTHOR_DATE=\"${date}\" GIT_COMMITTER_DATE=\"${date}\" git tag -f -a $0 $0^{}; }; f '"
Hält
1
Hab es gerade versucht. Anstatt dem Ersatz-Tag die Autoren- und Datumsinformationen aus dem Tag selbst zu geben, werden die Informationen aus dem Commit verwendet, auf das das Tag verweist. Dies ist nicht unbedingt dasselbe und in der Tat für unseren Fall die meiste Zeit nicht dasselbe. Wir haben eine Multi-Repo-Infrastruktur und verwenden kommentierte Tags in einem 'Core'-Repo, um Informationen über Pushs aufzuzeichnen, die mehrere Repos umfassen. Im Kern ist das Commit, auf das hingewiesen wird, möglicherweise nicht einmal Teil des eigentlichen Vorstoßes. Die Informationen im mit Anmerkungen versehenen Tag sollten die tatsächlichen Pushs in den anderen Repos widerspiegeln.
Tanager
0

Wenn Sie eine GUI wie verwenden SmartGit nur

  1. Erstellen Sie dasselbe Tag erneut an derselben Position mit der neuen Nachricht
  2. Wählen Sie "Vorhandenes Tag überschreiben".
  3. Drücken Sie das Tag zwangsweise in das Upstream-Repository
rubo77
quelle