web-dev-qa-db-ger.com

Was ist ein Git-Tag? Wie erstelle ich Tags?

wenn ich das Remote-Git-Tag auschecke, benutze ich den folgenden Befehl:

git checkout -b local_branch_name Origin/remote_tag_name

Ich habe folgende Fehlermeldung 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.

408
Ryanqy

Beginnen wir damit, zu erklären, was ein Tag in git ist

enter image description here

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.).

Ein Tag kann zwar ähnlich wie ein Zweig aussehen, ein Tag ändert sich jedoch nicht .
Es verweist direkt auf ein bestimmtes Commit in der Geschichte.

enter image description here


Sie können die Tags nicht auschecken, wenn sie sich nicht lokal in Ihrem Repository befinden. Daher müssen Sie zuerst die Tags in Ihrem lokalen Repository fetch.

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

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

Dann checke das Tag aus, indem du

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

Verwenden Sie anstelle von Origin das Präfix tags/.


In diesem Beispiel haben Sie 2 Tags, Version 1.0 und Version 1.1, die Sie mit einer der folgenden Methoden auschecken können:

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

Alle oben genannten Aktionen werden dasselbe tun, da tag nur ein Zeiger auf ein bestimmtes Commit ist.

enter image description here
Origin: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Wie wird die Liste aller Tags angezeigt?

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

# normal 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 wie in einem Git-Commit hinzufügen können:
Name, E-Mail, Datum, Kommentar & Unterschrift

enter image description here

Wie lösche ich Tags?

# delete any given tag
git tag -d <tag name>

# Don't forget to remove the deleted tag form the server with Push tags

Wie kann ich ein bestimmtes Tag klonen?

Um den Inhalt eines bestimmten Tags abzurufen, können Sie den Befehl checkout verwenden.
Wie oben erklärt, sind Tags wie alle anderen Commits, so dass wir checkout verwenden können und anstelle des SHA-1 einfach den tag_name verwenden können.

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:

Den Befehl clone verwenden

Da Git das flache Klonen unterstützt , indem dem Klonbefehl --branch hinzugefügt wird, können wir anstelle des Verzweigungsnamens den Tag-Namen verwenden. Git weiß, wie man den angegebenen 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 entgegennehmen und das HEAD bei diesem Commit im resultierenden Repository entfernen.

880
CodeWizard

(Das Schreiben dieser Antwort hat eine Weile gedauert, und Antwort von codeWizard ist in Ziel und Inhalt korrekt, aber nicht vollständig, daher werde ich dies trotzdem posten.)


Es gibt keinen "entfernten Git-Tag". Es gibt nur "Tags". Ich weise darauf hin, nicht pedantisch zu sein,1 Aber weil es bei Gelegenheits-Git-Benutzern eine Menge Verwirrung darüber gibt und die Git-Dokumentation nicht sehr hilfreich ist2 für Anfänger. (Es ist nicht klar, ob die Verwirrung auf eine schlechte Dokumentation zurückzuführen ist, oder ob die Dokumentation von Natur aus etwas verwirrend ist, oder was.)

Es gibt are "entfernte Zweige", genauer gesagt "entfernte Verfolgungszweige", aber es ist erwähnenswert, dass dies tatsächlich lokale Einheiten sind. 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 - Verweise aufruft - ist eine beliebige Zeichenfolge, die mit refs/ beginnt. Eine Zeichenfolge, die mit refs/heads/ beginnt, benennt einen Zweig. Eine Zeichenfolge, die mit refs/remotes/ beginnt, gibt einen Zweig für die Fernverfolgung an. und eine Zeichenfolge, die mit refs/tags/ beginnt, benennt ein Tag. Der Name refs/stash ist die Stash-Referenz (wie von git stash verwendet; beachten Sie das Fehlen eines abschließenden Schrägstrichs).

Es gibt einige ungewöhnliche Sonderfallnamen, die nicht mit refs/ beginnen: HEAD, ORIG_HEAD, MERGE_HEAD und CHERRY_PICK_HEAD sind insbesondere auch Namen, die sich auf bestimmte Commits beziehen können (obwohl HEAD normalerweise den Namen eines Zweigs enthält, dh ref: refs/heads/branch enthält). Verweise beginnen jedoch im Allgemeinen mit refs/.

Eine Sache, die Git macht, um dies zu verwirren, ist, dass Sie das refs/ und oft das Wort nach refs/ weglassen können. Beispielsweise können Sie refs/heads/ oder refs/tags/ weglassen, wenn Sie auf eine lokale Verzweigung oder ein lokales Tag verweisen - und tatsächlich müssen Sie weglassen refs/heads/ beim Auschecken einer lokalen Filiale! 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 stimmt, dass Referenzen nicht nur in Ihrem eigenen Repository, sondern auch in Remote-Repositorys vorhanden sind. Git gibt Ihnen jedoch nur zu bestimmten Zeiten Zugriff auf die Referenzen eines Remote-Repositorys: nämlich während fetch- und Push -Operationen. Sie können auch git ls-remote oder git remote show verwenden, um sie anzuzeigen, aber fetch und Push sind die interessanteren Kontaktpunkte.

Refspecs

Während fetch und Push verwendet Git Strings, die es 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. Bei fetch gibt es jedoch eine besondere Magie, die sich sowohl auf Zweignamen als auch auf Tag-Namen auswirkt.

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

Werfen wir einen Blick auf die normale Referenzspezifikation für die Fernbedienung mit dem Namen Origin:

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

Diese Refspezifikation weist Ihren Git an, jeden Namen, der mit refs/heads/* übereinstimmt, dh jeden Zweig auf der Fernbedienung, zu übernehmen und seinen Namen in refs/remotes/Origin/* zu ändern, dh den übereinstimmenden Teil unverändert zu lassen Filialname (refs/heads/) zu einem Filialnamen für die Fernverfolgung (refs/remotes/, insbesondere refs/remotes/Origin/).

Es ist durch diese Referenz , dass die Zweige von Origin Ihre Remote-Tracking-Zweige für remote Origin werden. Der Filialname wird zum Filialnamen der Fernverfolgung, einschließlich des Namens der Fernverfolgung, in diesem Fall Origin. Das Pluszeichen + vorne in der Referenzspezifikation setzt das Flag "force", d. H. Ihr Zweig zur Fernverfolgung wird so aktualisiert, dass er mit dem Zweignamen der Fernbedienung übereinstimmt, unabhängig davon, was für eine Übereinstimmung erforderlich ist. (Ohne das + sind Zweigaktualisierungen auf "Schnellvorlauf" -Änderungen beschränkt, und Tag-Aktualisierungen werden seit Git Version 1.8.2 oder so einfach ignoriert - davor galten dieselben Schnellvorlaufregeln.)

Stichworte

Aber was ist mit Tags? Es gibt keine Refspezifikation für sie - zumindest nicht standardmäßig. Sie können eine festlegen. In diesem Fall liegt die Form der Referenz bei Ihnen. oder Sie können git fetch --tags ausführen. Die Verwendung von --tags bewirkt, dass refs/tags/*:refs/tags/* zur Referenzspezifikation hinzugefügt wird, d. H., Dass alle Tags (aber aktualisiert nicht Ihr Tag, wenn Sie bereits ein Tag mit diesem Namen haben, unabhängig davon, was das Tag der Fernbedienung angibt  Edit, Januar 2017: Ab Git 2.10 zeigen Tests, dass --tags Ihre Tags zwangsweise von den Tags der Fernbedienung aktualisiert, als ob die Referenz +refs/tags/*:refs/tags/* lesen würde. Dies kann ein Unterschied im Verhalten gegenüber einer früheren Version von Git sein.

Beachten Sie, dass hier keine Umbenennung erfolgt: Wenn remote Origin das Tag xyzzy hat und Sie dies nicht tun und Sie git fetch Origin "refs/tags/*:refs/tags/*", erhalten Sie refs/tags/xyzzy zu Ihrem Repository hinzugefügt (verweist auf dasselbe Commit wie auf der Fernbedienung). Wenn Sie +refs/tags/*:refs/tags/* verwenden, wird Ihr Tag xyzzy, falls Sie eines haben, ersetzt durch das von Origin. Das bedeutet, dass das + Force-Flag auf einer Referenzspezifikation bedeutet, dass der Wert meiner Referenz durch den Wert ersetzt wird, den mein Git von seinem Git erhält.

Automagic-Tags während des Abrufs

Aus historischen Gründen3 Wenn Sie weder die Option --tags noch die Option --no-tags verwenden, führt git fetch eine spezielle Aktion aus. Denken Sie daran, dass wir oben gesagt haben, dass die Fernbedienung beginnt, indem sie Ihrem lokalen Git all anzeigt, ob Ihr lokaler Git sie sehen möchte oder nicht.4 Ihr Git nimmt alle Tags zur Kenntnis, die er zu diesem Zeitpunkt sieht. Wenn eines dieser Commits dieselbe ID wie eines dieser Tags hat, fügt git zu Beginn des Herunterladens von Commit-Objekten, die für den Abruf benötigt werden, dieses Tag hinzu (oder diese Tags, wenn mehrere Tags diese ID haben) Ihr Repository.

Edit, Jan 2017: Tests zeigen, dass das Verhalten in Git 2.10 jetzt ist: Wenn ihr Git ein Tag namens [~ # ~] t [~ # ~] , und Sie haben kein Tag mit dem Namen [~ # ~] t [~ # ~] , und Die mit [~ # ~] t [~ # ~] verknüpfte Festschreibungs-ID ist ein Vorfahr eines ihrer Zweige, die Ihr git fetch ist Untersucht, fügt Ihr Git [~ # ~] t [~ # ~] zu Ihren Tags mit oder ohne --tags hinzu. Durch das Hinzufügen von --tags erhält Ihr Git die Tags all und erzwingt auch die Aktualisierung.

Endeffekt

Möglicherweise müssen Sie git fetch --tags verwenden, um ihre Tags abzurufen. Wenn ihre Tag-Namen mit Ihren vorhandenen Tag-Namen in Konflikt stehen, müssen Sie (abhängig von der Git-Version) sogar einige Ihrer Tags löschen (oder umbenennen) und dann git fetch --tags, um ihre Tags abzurufen. Da Tags im Gegensatz zu Remotezweigen 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 jedoch ein einfaches git fetch die Aufgabe und überträgt ihre Commits und ihre passenden Tags, und da sie - wer auch immer sie sind - Wenn Commits mit Tags versehen werden, sobald sie veröffentlicht werden, bleiben Sie mit ihren Tags auf dem Laufenden. Wenn Sie keine eigenen Tags erstellen oder deren Repository und andere Repositorys (über mehrere Remotes) nicht mischen, kommt es auch nicht zu Tag-Namenskollisionen, sodass Sie keine Probleme mit dem Löschen oder Umbenennen von Tags haben erhalten ihre Tags.

Wenn Sie qualifizierte Namen benötigen

Ich erwähnte oben, dass Sie refs/ fast immer weglassen können, und refs/heads/ und refs/tags/ und so weiter die meiste Zeit. Aber wann können nicht Sie?

Die vollständige (oder fast vollständige) Antwort ist in die gitrevisions Dokumentation . Git löst einen Namen in eine Festschreibungs-ID mit der im Link angegebenen sechsstufigen Sequenz auf. Merkwürdigerweise überschreiben Tags Zweige: Wenn es ein Tag xyzzy und einen Zweig xyzzy gibt und sie auf verschiedene Commits verweisen, dann:

git rev-parse xyzzy

gibt Ihnen die ID, auf die das Tag zeigt. Allerdings - und genau das fehlt in gitrevisions - git checkout bevorzugt Zweignamen, sodass git checkout xyzzy Sie in den Zweig versetzt und das Tag ignoriert.

Im Zweifelsfall können Sie den Referenznamen fast immer mit dem vollständigen Namen refs/heads/xyzzy oder refs/tags/xyzzy buchstabieren. (Beachten Sie, dass dies nicht mit git checkout funktioniert, aber auf eine möglicherweise unerwartete Weise: git checkout refs/heads/xyzzy führt zu einer Ablösung von HEAD anstelle von a Auschecken von Zweigen: Aus diesem Grund müssen Sie nur beachten, dass git checkout zuerst den Kurznamen als Zweignamen verwendet: So können Sie den Zweig xyzzy auschecken, auch wenn das Tag xyzzy existiert. Wenn Sie das Tag auschecken möchten, können Sie refs/tags/xyzzy verwenden.)

Da Git (als gitrevisions Notizen) refs/name versucht, können Sie auch einfach tags/xyzzy schreiben, um das mit dem Commit-Tag xyzzy zu identifizieren. (Wenn es jemandem gelungen ist, eine gültige Referenz mit dem Namen xyzzy in $GIT_DIR zu schreiben, wird dies als $GIT_DIR/xyzzy aufgelöst. Normalerweise werden jedoch nur die verschiedenen *HEAD Namen sollten in $GIT_DIR sein.)


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

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

3Grundsätzlich war git fetch und das gesamte Konzept der Fernbedienungen und Refspecs eine späte Erweiterung von Git, die um die Zeit von Git 1.5 erfolgte. Zuvor gab es nur einige Ad-hoc-Sonderfälle, und das Abrufen von Tags war einer von ihnen. Daher wurde es über speziellen Code eingeführt.

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

179
torek

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

0
Rahul Khatri