Was ist ein Git-Tag? Wie erstelle ich Tags? & Wie checke ich Git-Remote-Tags aus?

524

Wenn ich das Remote-Git-Tag auschecke, verwenden Sie den folgenden Befehl:

git checkout -b local_branch_name origin/remote_tag_name

Ich habe folgenden Fehler erhalten:

error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.

Ich kann remote_tag_name finden, wenn ich den Befehl git tag verwende.

Ryanqy
quelle

Antworten:

1155

Beginnen wir mit der Erklärung, was ein Tag in Git ist

Geben Sie hier die Bildbeschreibung ein

Ein Tag wird verwendet, um ein bestimmtes Commit im Verlauf zu kennzeichnen und zu markieren .
Es wird normalerweise zum Markieren von Freigabepunkten verwendet (z. B. v1.0 usw.).

Obwohl ein Tag möglicherweise einem Zweig ähnelt , ändert sich ein Tag nicht . Es verweist direkt auf ein bestimmtes Commit in der Historie.

Geben Sie hier die Bildbeschreibung ein


Sie können die Tags nicht auschecken, wenn sie sich nicht lokal in Ihrem Repository befinden. Zuerst müssen Sie fetchdie Tags in Ihrem lokalen Repository speichern.

Stellen Sie zunächst sicher, dass das Tag lokal vorhanden ist

# --all will fetch all the remotes.
# --tags will fetch all tags as well
$ git fetch --all --tags --prune

Überprüfen Sie dann das Tag, indem Sie es ausführen

$ git checkout tags/<tag_name> -b <branch_name>

Anstatt origindas tags/Präfix zu verwenden.


In diesem Beispiel haben Sie 2 Tags, Version 1.0 und Version 1.1. Sie können sie mit einer der folgenden Optionen überprüfen:

$ git checkout A  ...
$ git checkout version 1.0  ...
$ git checkout tags/version 1.0  ...

Alle oben genannten Schritte machen dasselbe, da das Tag nur ein Zeiger auf ein bestimmtes Commit ist.

Geben Sie hier die Bildbeschreibung ein
Herkunft: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Wie sehe ich die Liste aller Tags?

# list all tags
$ git tag

# list all tags with given pattern ex: v-
$ git tag --list 'v-*'

Wie erstelle ich Tags?

Es gibt zwei Möglichkeiten, ein Tag zu erstellen:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

Der Unterschied zwischen den beiden besteht darin, dass Sie beim Erstellen eines mit Anmerkungen versehenen Tags Metadaten hinzufügen können, wie Sie sie in einem Git-Commit haben:
Name, E-Mail, Datum, Kommentar und Signatur

Geben Sie hier die Bildbeschreibung ein

Wie lösche ich Tags?

# delete any (local) given tag
$ git tag -d <tag name>

# Delete a tag from the server with push tags
$ git push --delete origin <tag name>

Wie klone ich ein bestimmtes Tag?

Um den Inhalt eines bestimmten Tags abzurufen, können Sie den checkoutBefehl verwenden. Wie oben erläutert, sind Tags wie alle anderen Commits, sodass wir sie verwenden können checkoutund statt SHA-1 einfach durch den Tag-Namen zu ersetzen

Option 1:

# Update the local git repo with the latest tags from all remotes
$ git fetch --all

# checkout the specific tag
$ git checkout tags/<tag> -b <branch>

Option 2:

Verwenden des Befehls clone

Da git das flache Klonen durch Hinzufügen des --branchBefehls zum Klon unterstützt, können wir den Tag-Namen anstelle des Verzweigungsnamens verwenden. Git weiß, wie man den gegebenen SHA-1 in das entsprechende Commit "übersetzt"

# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

Git-Klon --branch =

--branch kann auch Tags nehmen und den HEAD bei diesem Commit im resultierenden Repository trennen.


Wie man Tags pusht?

git push --tags

So pushen Sie alle Tags:

# Push all tags
$ git push --tags 

Verwenden Sie das, refs/tagsanstatt nur das anzugeben <tagname>.

Warum? - Es wird empfohlen, diese zu verwenden, refs/tagsda Tags manchmal denselben Namen wie Ihre Zweige haben können und durch einfaches Git-Push der Zweig anstelle des Tags verschoben wird

Verwenden Sie Folgendes, um mit Anmerkungen versehene Tags und aktuelle Verlaufsketten-Tags zu verschieben:

git push --follow-tags

Dieses Flag --follow-tagsüberträgt beide Commits und nur Tags , die beide sind:

  • Kommentierte Tags (damit Sie lokale / temporäre Build-Tags überspringen können)
  • Erreichbare Tags (ein Vorfahr) aus dem aktuellen Zweig (im Verlauf)

Geben Sie hier die Bildbeschreibung ein

Ab Git 2.4 können Sie es mithilfe der Konfiguration festlegen

$ git config --global push.followTags true

Spickzettel: Geben Sie hier die Bildbeschreibung ein


CodeWizard
quelle
3
nett. git checkout A. was ist A? Wie hast du geschaffen A?
Honig
3
@ CodeWizard Schönes Flussdiagramm! Mit welcher Software haben Sie es erstellt?
Giovanni Lovato
4
@Honey Aist ein Commit-Hash
Alex Baklanov
2
@GiovanniLovato Das Flussdiagramm ist ein Diagramm eines Drittanbieters. Der Link zum Bild lautet backlog.com/git-tutorial/img/post/stepup/… und befindet sich auf dieser Seite backlog.com/git-tutorial/stepup/stepup4_1.html der Website mit dem Namen Git Beginner's Guide for Dummies (Backlog) .com).
George
2
Es ist erwähnenswert, dass git checkout tags/<tag_name> -b <branch_name>das erfordert -b <branch_name>. git checkout tags/<tag_name>gab mir einen losgelösten Kopf. Gemäß diesem Artikel über abgetrennten Kopf vermeiden Sie einen abgetrennten Kopf, indem Sie vorübergehend einen Zweig erstellen und löschen. Dies ist ein ziemlich fremder Arbeitsablauf. Natürlich muss ich mich als Git-Benutzer daran gewöhnen, Zweige zum Spaß und zum Profit zu erstellen und zu löschen.
icc97
194

(Das Schreiben dieser Antwort hat eine Weile gedauert , und die Antwort von codeWizard ist in Ziel und Wesen korrekt, aber nicht vollständig, daher werde ich sie trotzdem veröffentlichen.)


Es gibt kein "Remote-Git-Tag". Es gibt nur "Tags". Ich weise darauf hin, dass dies alles nicht pedantisch ist 1, aber weil dies bei gelegentlichen Git-Benutzern sehr verwirrend ist und die Git-Dokumentation für Anfänger nicht sehr hilfreich ist 2 . (Es ist nicht klar, ob die Verwirrung auf eine schlechte Dokumentation zurückzuführen ist oder ob die schlechte Dokumentation darauf zurückzuführen ist, dass dies von Natur aus etwas verwirrend ist, oder was.)

Es gibt "Remote-Zweige", besser gesagt "Remote-Tracking-Zweige", aber es ist erwähnenswert, dass es sich tatsächlich um lokale Entitäten handelt. Es gibt jedoch keine Remote-Tags (es sei denn, Sie erfinden sie (neu)). Es gibt nur lokale Tags, daher müssen Sie das Tag lokal abrufen, um es verwenden zu können.

Die allgemeine Form für Namen für bestimmte Commits, die Git als Referenzen bezeichnet, ist eine beliebige Zeichenfolge, die mit beginnt refs/. Eine Zeichenfolge, die mit refs/heads/Namen eines Zweigs beginnt . eine Zeichenfolge, die mit refs/remotes/Namen eines Fernverfolgungszweigs beginnt ; und eine Zeichenfolge, die mit refs/tags/Namen eines Tags beginnt . Der Name refs/stashist die Stash-Referenz (wie von verwendet git stash; beachten Sie das Fehlen eines abschließenden Schrägstrichs).

Es gibt einige ungewöhnliche Spezialfall - Namen , die mit nicht beginnen refs/: HEAD, ORIG_HEAD, MERGE_HEAD, und CHERRY_PICK_HEADinsbesondere sind auch alle Namen, die auf bestimmte Commits beziehen (obwohl HEADnormalerweise den Namen eines Zweigs enthält, dh enthält ). Im Allgemeinen beginnen Referenzen jedoch mit .ref: refs/heads/branchrefs/

Eine Sache, die Git macht, um dies verwirrend zu machen, ist, dass Sie das refs/und oft das Wort danach weglassen können refs/. Zum Beispiel können Sie weglassen refs/heads/oder refs/tags/auf einen lokalen Zweig oder Tag verweisen - und tatsächlich müssen Sie refs/heads/beim Auschecken eines lokalen Zweigs weglassen ! Sie können dies tun, wenn das Ergebnis eindeutig ist oder - wie wir gerade bemerkt haben - wenn Sie es tun müssen (für ).git checkout branch

Es ist richtig, dass Referenzen nicht nur in Ihrem eigenen Repository vorhanden sind, sondern auch in Remote-Repositorys. Mit Git können Sie jedoch nur zu bestimmten Zeiten auf die Referenzen eines Remote-Repositorys zugreifen: nämlich während fetchund während des pushVorgangs. Sie können auch verwenden git ls-remoteoder git remote showsie zu sehen, aber fetchund pushsind die interessanteren Berührungspunkte.

Refspecs

Während fetchund pushverwendet Git Zeichenfolgen, die refspecs aufruft , um Referenzen zwischen dem lokalen und dem Remote-Repository zu übertragen. Daher können zu diesen Zeiten und über Refspecs zwei Git-Repositorys miteinander synchronisiert werden. Sobald Ihre Namen synchronisiert sind, können Sie denselben Namen verwenden, den jemand mit der Fernbedienung verwendet. Hier gibt es jedoch eine besondere Magie fetch, die sowohl Zweig- als auch Tag-Namen betrifft.

Sie sollten sich vorstellen git fetch, Ihren Git anzuweisen, einen anderen Git - die "Fernbedienung" - aufzurufen (oder eine SMS zu senden) und mit ihm zu sprechen. Zu Beginn dieses Gesprächs listet die Fernbedienung alle ihre Referenzen auf: alles in refs/heads/und alles in refs/tags/, zusammen mit allen anderen Referenzen, die sie hat. Ihr Git durchsucht diese und benennt (basierend auf der üblichen Abrufreferenz) ihre Zweige um.

Werfen wir einen Blick auf die normale Referenz für die Fernbedienung mit dem Namen origin:

$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$ 

Diese Refspec weist Git jeden Namen passend zu nehmen refs/heads/*-ie, jeden Zweig auf dem Remote-und seinen Namen ändern refs/remotes/origin/*, das heißt, halten Sie den angepassten Teil die gleiche, die Zweignamen (Ändern refs/heads/) zu einem Remote-Tracking - Zweignamen ( refs/remotes/speziell , refs/remotes/origin/).

Es ist durch diese Refspec , dass origin‚s Filialen für Fern Ihre Fernverfolgung Zweige werden origin. Der Filialname wird zum Remote-Tracking-Filialnamen, wobei der Name der Remote in diesem Fall originenthalten ist. Das Pluszeichen +an der Vorderseite der Referenzspezifikation setzt das "Force" -Flag, dh Ihr Fernverfolgungszweig wird aktualisiert, um mit dem Zweigstellennamen der Fernbedienung übereinzustimmen, unabhängig davon, was erforderlich ist, um die Übereinstimmung herzustellen. (Ohne das +sind Verzweigungsaktualisierungen auf Änderungen beim "schnellen Vorlauf" beschränkt, und Tag-Aktualisierungen werden seit Git-Version 1.8.2 oder so einfach ignoriert - zuvor wurden dieselben Regeln für den schnellen Vorlauf angewendet.)

Stichworte

Aber was ist mit Tags? Es gibt keine Referenz für sie - zumindest nicht standardmäßig. Sie können eine festlegen. In diesem Fall liegt die Form der Referenz bei Ihnen. oder du kannst rennen git fetch --tags. Die Verwendung --tagshat den Effekt refs/tags/*:refs/tags/*, dass die Refspec hinzugefügt wird, dh alle Tags werden übertragen ( aktualisiert Ihr Tag jedoch nicht, wenn Sie bereits ein Tag mit diesem Namen haben, unabhängig davon, was auf dem Tag der Fernbedienung steht. Bearbeiten, Januar 2017: ab Git 2.10 Tests haben gezeigt, dass --tagsIhre Tags zwangsweise von den Tags der Fernbedienung aktualisiert werden, als ob die Referenzspezifikation gelesen hätte +refs/tags/*:refs/tags/*(dies kann ein Unterschied im Verhalten gegenüber einer früheren Version von Git sein).

Beachten Sie, dass hier keine Umbenennung erfolgt: Wenn remote originein Tag xyzzyhat und Sie dies nicht tun git fetch origin "refs/tags/*:refs/tags/*", werden Sie refs/tags/xyzzyzu Ihrem Repository hinzugefügt (und verweisen auf dasselbe Commit wie auf der Remote). Wenn Sie +refs/tags/*:refs/tags/*dann Ihren Tag xyzzy, wenn Sie eine haben, wird ersetzt durch einen aus origin. Das heißt, das +Force-Flag in einer Referenz bedeutet "Ersetzen Sie den Wert meiner Referenz durch den Wert, den mein Git von seinem Git erhält".

Automagische Tags beim Abrufen

Aus historischen Gründen 3 ergreift 3, wenn Sie weder die --tagsOption noch die --no-tagsOption verwenden, git fetchbesondere Maßnahmen. Denken Sie daran, dass wir oben gesagt haben, dass die Fernbedienung zunächst Ihrem lokalen Git alle Referenzen anzeigt , unabhängig davon, ob Ihr lokaler Git sie sehen möchte oder nicht. 4 Ihr Git nimmt alle Tags zur Kenntnis, die es an dieser Stelle sieht. Wenn dann das Herunterladen von Commit-Objekten beginnt, die für das Abrufen benötigt werden, fügt git dieses Tag - oder diese Tags, wenn mehrere Tags diese ID haben - hinzu, wenn eines dieser Commits dieselbe ID wie eines dieser Tags hat Ihr Repository.

Bearbeiten, Januar 2017: zeigt die Prüfung , dass das Verhalten in Git 2.10 ist nun: Wenn sie Git einen Tag mit dem Namen liefert T , und Sie haben keinen Tag mit dem Namen T , und die Commit - ID mit zugehörigem T ist ein Vorfahre eines ihres Zweiges Wenn Sie git fetchprüfen, fügt Ihr Git Ihren Tags mit oder ohne T hinzu --tags. Durch --tagsdas Hinzufügen erhält Ihr Git alle Tags und erzwingt auch die Aktualisierung.

Endeffekt

Möglicherweise müssen Sie verwenden git fetch --tags, um ihre Tags zu erhalten. Wenn ihre Tag-Namen mit Ihren vorhandenen Tag-Namen in Konflikt stehen, müssen Sie möglicherweise (abhängig von der Git-Version) sogar einige Ihrer Tags löschen (oder umbenennen) und dann ausführen git fetch --tags, um ihre Tags abzurufen. Da Tags im Gegensatz zu Remote-Zweigen nicht automatisch umbenannt werden, müssen Ihre Tag-Namen mit ihren Tag-Namen übereinstimmen. Aus diesem Grund können Probleme mit Konflikten auftreten.

In den meisten normalen Fällen erledigt ein einfacher git fetchBenutzer die Aufgabe, indem er seine Commits und die passenden Tags überträgt. Da sie - wer auch immer sie sind - Commits zum Zeitpunkt der Veröffentlichung dieser Commits markieren, werden Sie mit ihren Tags Schritt halten. Wenn Sie keine eigenen Tags erstellen oder deren Repository und andere Repositorys nicht mischen (über mehrere Fernbedienungen), treten auch keine Kollisionen mit Tag-Namen auf, sodass Sie sich nicht um das Löschen oder Umbenennen von Tags kümmern müssen erhalten ihre Tags.

Wenn Sie qualifizierte Namen benötigen

Ich erwähnte oben , dass man weglassen kann refs/fast immer, und refs/heads/und refs/tags/und so weiter die meiste Zeit. Aber wann kannst du nicht ?

Die vollständige (oder fast vollständige) Antwort finden Sie in der gitrevisionsDokumentation . Git löst einen Namen in eine Commit-ID unter Verwendung der im Link angegebenen sechsstufigen Sequenz auf. Seltsamerweise überschreiben Tags Zweige: Wenn es ein Tag xyzzyund einen Zweig xyzzygibt und sie auf unterschiedliche Commits verweisen, dann:

git rev-parse xyzzy

gibt Ihnen die ID, auf die das Tag verweist. Allerdings - und genau das fehlt in gitrevisions- werden git checkoutZweigstellennamen bevorzugt, sodass git checkout xyzzySie in den Zweig gelangen und das Tag nicht berücksichtigen.

Bei Unklarheiten können Sie den Referenznamen fast immer mit seinem vollständigen Namen refs/heads/xyzzyoder buchstabieren refs/tags/xyzzy. (Beachten Sie, dass dies tut Arbeit mit git checkout, aber auf eine vielleicht unerwartete Weise: git checkout refs/heads/xyzzyführt eine freistehende-HEAD Kasse eher als ein Zweig der Kasse diesem Grund sollten Sie nur zu Kenntnis haben , die. git checkoutDen Kurznamen als Zweignamen zuerst verwenden: Das ist , wie Sie Überprüfen Sie den Zweig, xyzzyauch wenn das Tag xyzzyvorhanden ist. Wenn Sie das Tag auschecken möchten, können Sie es verwenden refs/tags/xyzzy.)

Da (als gitrevisionsNotizen) Git es versucht , können Sie auch einfach schreiben , um das mit Tags versehene Commit zu identifizieren . (Wenn es jemandem gelungen ist, eine gültige Referenz mit dem Namen in zu schreiben , wird dies wie folgt aufgelöst . Normalerweise sollten jedoch nur die verschiedenen Namen in sein .)refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


1 Okay, okay, "nicht nur um pedantisch zu sein". :-)

2 Einige würden "sehr nicht hilfreich" sagen, und ich würde eher zustimmen.

3 Grundsätzlich git fetchund das gesamte Konzept von Fernbedienungen und Refspecs war eine etwas späte Ergänzung zu Git, die um die Zeit von Git 1.5 herum stattfand. Zuvor gab es nur einige Ad-hoc-Sonderfälle, und das Abrufen von Tags war einer davon, sodass es über einen speziellen Code großväterlich behandelt wurde.

4 Wenn es hilft, stellen Sie sich das entfernte Git als Blinker im Slang vor.

torek
quelle
Großartige Zusammenfassung. Ein winziger Fehler: git fetchRuft nur die Tags der Fernbedienung ab, wenn das --tagsArgument vorliegt.
zweiwöchentlich
@cweekly: das Verhalten --tags, --no-tagsund das Standard ist eigentlich ziemlich schwierig. Standardmäßig werden Tags eingefügt, die nicht in den von Ihnen eingebrachten Commits enthalten sind. (Siehe die Bearbeitung vom Januar 2017.) Aber auch hier gibt es Pannen, und das moderne Git hat seine --tags / --no-tags-Bearbeitungscode wurde erneut überarbeitet, was wahrscheinlich zu noch spezielleren Eckfällen führen wird.
Torek
1

Um ein Git-Tag auszuchecken, führen Sie den folgenden Befehl aus

git checkout tags/tag-name -b branch-name

zB wie unten erwähnt.

 git checkout tags/v1.0 -b v1.0-branch

Verwenden Sie den Befehl, um alle Tags abzurufen

git fetch --all --tags
Mani
quelle
0

Um den spezifischen Tag-Code zu erhalten, versuchen Sie, einen neuen Zweig zu erstellen. Fügen Sie den Tag-Code hinzu. Ich habe es auf Befehl getan:$git checkout -b newBranchName tagName

Rahul Khatri
quelle