Wie kann ich ein Tag in einem Git-Zweig in ein anderes Commit verschieben?

858

Ich habe im Hauptzweig ein Tag mit folgendem Namen erstellt v0.1:

git tag -a v0.1

Aber dann wurde mir klar, dass es noch einige Änderungen gab, die ich für Release 0.1 in Master einbinden musste, also habe ich das getan. Aber jetzt v0.1bleibt mein Tag beim falschen Festschreiben hängen (um die Post-It-Note-Analogie aufzurufen). Ich möchte, dass es beim letzten Commit auf dem Master hängen bleibt, aber stattdessen beim zweitletzten Commit auf dem Master.

Wie kann ich es auf das letzte Commit für den Master verschieben?

eedeep
quelle

Antworten:

1199

Verwenden Sie die -fOption, um git tag:

-f
--force

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

Sie möchten wahrscheinlich -fin Verbindung mit verwenden -a, um ein mit Anmerkungen versehenes Tag anstelle eines nicht mit Anmerkungen versehenen Tags zu erzwingen.

Beispiel

  1. Löschen Sie das Tag auf einer beliebigen Fernbedienung, bevor Sie drücken

    git push origin :refs/tags/<tagname>
    
  2. Ersetzen Sie das Tag, um auf das letzte Commit zu verweisen

    git tag -fa <tagname>
    
  3. Schieben Sie das Tag zum entfernten Ursprung

    git push origin master --tags
    
Greg Hewgill
quelle
90
Es kann eine gute Idee sein, das Tag auf einer beliebigen Fernbedienung zu löschen, bevor Sie ebenfalls einen Push ausführen: git push origin :refs/tag/<tagname>und dann tun git tag -fa <tagname>und dann git push origin master --tags. Andernfalls könnte es vorkommen, dass in der Refs-Liste auf der Fernbedienung seltsame Dinge mit angehängten Zeichen ^ und {} angezeigt werden. Vielen Dank an Dan von codebasehq.com für diesen Hinweis.
Eedeep
47
@eedeep: Kleinere Korrektur - stattdessen :refs/tag/<tagname>sollte es sein :refs/tags/<tagname>.
Ben Hocking
8
Dies funktioniert nur, wenn Sie den Code nicht von Ihrem Computer entfernt haben. Wenn ja, ist die beste Antwort "Es gibt viele Zahlen auf der Welt", da sich der Aufwand wahrscheinlich nicht lohnt.
Chris Huang-Leaver
33
Wenn Sie Ihr Tag bereits gepusht haben, können Sie das Remote-Tag dennoch mit einem erzwungenen Push git push -f origin <tagname>
aktualisieren
11
Was hier und in den Dokumenten nicht erwähnt wird, ist, dass dies tatsächlich die Tag-Nachricht verschiebt, wenn keine neue Nachricht gegeben wird.
Twonky
259

Genauer gesagt müssen Sie das Hinzufügen des Tags erzwingen und dann mit den Optionen --tags und -f drücken:

git tag -f -a <tagname>
git push -f --tags
Daniel
quelle
171

Um zusammenzufassen, ob Ihre Fernbedienung aufgerufen wird originund Sie an einem masterZweig arbeiten:

git tag -d <tagname>
git push origin :refs/tags/<tagname>
git tag <tagname> <commitId>
git push origin <tagname>
  • Zeile 1 entfernt das Tag in der lokalen Umgebung.
  • Zeile 2 entfernt das Tag in der Remote-Umgebung.
  • Zeile 3 fügt das Tag einem anderen Commit hinzu
  • Zeile 4 überträgt das Wechselgeld auf die Fernbedienung

Sie können auch Zeile 4 austauschen git push origin --tags, um alle Änderungen mit Tags aus Ihren lokalen Änderungen zu übertragen.

Basierend auf @ stuart-golodetz, @ greg-hewgill, @eedeep, @ ben-hocking Antworten, Kommentaren unter ihren Antworten und NateS Kommentaren unter meiner Antwort.

Vive
quelle
87

Löschen Sie es mit git tag -d <tagname>und erstellen Sie es dann beim richtigen Commit neu.

Stuart Golodetz
quelle
3
@eedeep: Ich denke, Gregs Antwort ist hier eigentlich besser, um fair zu sein.
Stuart Golodetz
Halte es einfach. Löschen Sie es, machen Sie das, was Sie zuvor getan haben.
Ooolala
1
Dies sollte der Einfachheit halber die akzeptierte Antwort sein. Wendet auch -f Gewalt nicht übermäßig an.
Chinnychinchin
48

Ich versuche ein paar Dinge zu vermeiden, wenn ich Git benutze.

  1. Verwendung von Kenntnissen der Interna, zB Refs / Tags. Ich versuche, nur die dokumentierten Git-Befehle zu verwenden und Dinge zu vermeiden, die Kenntnisse über den internen Inhalt des .git-Verzeichnisses erfordern. (Das heißt, ich behandle Git als Git-Benutzer und nicht als Git-Entwickler.)

  2. Die Anwendung von Gewalt, wenn nicht erforderlich.

  3. Dinge übertreiben. (Drücken eines Zweigs und / oder vieler Tags, um ein Tag dort zu erhalten, wo ich es haben möchte.)

Hier ist meine gewaltfreie Lösung zum Ändern eines Tags, sowohl lokal als auch remote, ohne Kenntnis der Git-Interna.

Ich benutze es, wenn ein Software-Fix letztendlich ein Problem hat und aktualisiert / erneut veröffentlicht werden muss.

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)

githubist ein Beispiel-Remote-Name, fix123ein Beispiel-Tag-Name und 790a621265ein Beispiel-Commit.

Ivan
quelle
26

Ich werde hier nur eine andere Form dieses Befehls belassen, die meinen Bedürfnissen entsprach.
Es gab ein Tag v0.0.1.2, das ich verschieben wollte.

$ git tag -f v0.0.1.2 63eff6a

Updated tag 'v0.0.1.2' (was 8078562)

Und dann:

$ git push --tags --force
Nakilon
quelle
gut, danke, 2 einfache Befehle
Sérgio
10

Ein anderer Weg:

Verschieben Sie das Tag im Remote-Repo. (Ersetzen Sie HEAD bei Bedarf durch ein anderes.)

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

Änderungen zurückholen.

$ git fetch --tags
Алексей Югов
quelle
Dies ist mehr "transaktional" als die anderen Antworten.
Justin M. Keyes
9

Alias ​​zum Verschieben eines Tags in ein anderes Commit.

Um in Ihrem Beispiel das Commit mit dem Hash e2ea1639 zu verschieben, gehen Sie wie folgt vor : git tagm v0.1 e2ea1639.

Verwenden Sie für Push-Tags git tagmp v0.1 e2ea1639.

Beide Alias ​​behalten Ihr ursprüngliches Datum und Ihre ursprüngliche Nachricht. Wenn Sie verwenden, haben git tag -dSie Ihre ursprüngliche Nachricht verloren.

Speichern Sie sie in Ihrer .gitconfigDatei

# 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 #"
Juan Antonio Tubío
quelle
1

Wenn Sie ein mit Anmerkungen versehenes Tag verschieben möchten, ändern Sie nur das Ziel-Commit, behalten jedoch die Verwendung der Anmerkungsnachricht und anderer Metadaten bei:

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 {}
}

Verwendung: moveTag <tag-to-move> <Ziel>

Die obige Funktion wurde unter Bezugnahme auf teerapap / git-move-annotated-tag.sh entwickelt .

vossad01
quelle
1
Es scheint, dass dies nicht mehr benötigt wird: git tag -f -a my_tagDie Nachricht einer vorherigen Nachricht (mit Git-Version 2.11.0) wird bereits beibehalten.
Matthijs Kooijman