19 Stimmen

Gelten Git-Tags für alle Branches?

Ich taste mich gerade an das Taggen mit Git heran, aber mein bisheriger Hintergrund liegt in Subversion, wo "Tags" eigentlich nur Kopien waren und keine "echten" Tags...

Wenn ich einem Git-Repository ein Tag hinzufüge, wird es auf alle Branches angewendet oder nur auf den aktuellen?

Zum Beispiel, wenn ich momentan diese Branches habe (git branch -v):

* master deadbeef Mein master head Kommentar
  dev    baddfeed Mein dev head Kommentar

Und der momentan ausgecheckte Branch ist master, wie du sehen kannst. Angenommen ich füge nun ein git tag -a TAGNAME hinzu, gilt TAGNAME dann nur für deadbeef (master branch) oder auch für baddfeed (dev branch)?

Zum Beispiel, wenn ich anschließend zum dev Branch wechsle (also nicht der Branch, auf dem das Tag erstellt wurde) bevor ich das Tag auschecke:

git checkout dev
git checkout TAGNAME

Lande ich dann beim Auschecken bei baddfeed oder bringt mich das Tag-Auschecken (zweite Zeile) zurück zum master Branch (wo das Tag erstellt wurde) und bekomme ich ein Auschecken von deadbeef? (Oder ist meine Vorstellung von Tag-Erstellung und Wiederherstellung zu fehlerhaft oder zu simpel für die Antwort, um so einfach wie eine dieser beiden Optionen zu sein?)

Ändert sich die Antwort auf meine Frage, wenn ich ein lightweight tag (git tag TAGNAME) anstelle eines annotierten Tags verwende?

22voto

Jean Waghetti Punkte 4651

Sagen wir, du bist im Branch myBranch. Und du erstellst ein Tag namens myTag

-----A-----B-----C-----D-----H-------I-----> master
                       \
                        \
                         \---E----F-----G-----> myBranch
                                        |
                                        myTag

Das Tag wird nur auf dem Commit-Objekt des Zweigs myBranch sein. Ich habe auch mit CVS gearbeitet, und es markiert auch Revisionen, nicht alle Branches (aber in CVS sind Branches spezielle Tags). Das glaube ich nicht.

Wenn du zu myTag wechselst, wirst du im Commit G des Beispiels sein. Du kannst keine Tags mit demselben Namen in verschiedenen Branches erstellen. Wenn du es versuchst, verschiebst du das Tag.

Es macht keinen Unterschied für ein annotiertes Tag in Bezug darauf.

Hinweis: Wenn du Tags auscheckst, landest du im "detached HEAD"-Modus. Deine Änderungen gehen verloren, es sei denn, du erstellst einen anderen Zweig, der vom ausgecheckten Tag aus startet.

9voto

torek Punkte 381305

Nachdem ich die Fragen und Ihre Kommentare gelesen habe, glaube ich, dass der grundlegende Punkt, der Sie hier verwirrt, ist, was es in git (im Vergleich zu anderen Systemen) bedeutet, "auf einem branch zu sein".

In git überprüft ein git checkout-Befehl einige bestimmte Commits [aber siehe Fußnote 1]. Es setzt auch den speziellen Namen HEAD, sodass er auf diesen bestimmten Commit verweist. Aber: es gibt zwei verschiedene Möglichkeiten, wie HEAD einen bestimmten Commit angeben kann. Es kann sein:

  • nach ID (dies ist der nicht-übliche Fall), oder
  • indirekt über Verweis auf einen branch-Namen (das ist der üblichere Fall).

Wenn Sie git checkout _branchname_ ausführen, setzt git den zweiten, üblichen Fall auf. Wenn Sie dann cat .git/refs/HEAD ausführen, werden Sie feststellen, dass es den Literalstring ref: enthält, gefolgt von refs/heads/_branchname_ [2]. Das bedeutet, dass Sie "auf dem branch" sind: Sie haben den Commit überprüft, auf den der branch-Name verweist, aber auch, HEAD ist ein "symbolischer Verweis". Wenn Sie Änderungen vornehmen und diese committen, wird git den neuen Commit erstellen, dann das branch-Label-Sticky-Note abziehen und auf den neuen Commit kleben. Das "bewegt den branch" zur neu hinzugefügten Spitze, und Sie sind "immer noch auf dem branch".

Auf der anderen Seite, wenn Sie git checkout _tagname_ ausführen, setzt git den ersten, ungewöhnlichen Fall auf. Das macht es auch, wenn Sie über die SHA-1-ID (diese ea56709...-ähnlichen Zeichenfolgen) auschecken. In diesem Fall enthält die Datei für HEADHEAD ist kein "symbolischer Verweis".

Was die tatsächlichen Tags selbst betrifft, handelt es sich lediglich um Namen für Commits. Aber Moment mal, ist das nicht das, was ein branch-Name ist? Ja! Der Unterschied zwischen einem branch-Namen und einem Tag-Namen besteht darin, dass von einem branch-Namen erwartet wird, dass er sich bewegt, und git wird ihn automatisch in diesem "auf einem branch" Fall verschieben. Ein Tag-Name wird nicht "erwartet, sich zu bewegen" [3] und wird sich nie automatisch bewegen.


Fußnoten:

[1] Nur um die Dinge zu verkomplizieren (oder weil die Benutzeroberfläche von git "böse" ist, wie manche sagen würden :-) ) gibt es Fälle, in denen git checkout nicht HEAD ändert, insbesondere wenn Sie es auffordern, bestimmte Pfadnamen zu überprüfen.

[2] In sehr alten Versionen von git wurde anstelle von ref: ... ein symbolischer Link verwendet. Das Ziel des Links war die branch-ID-Datei, z. B. refs/heads/master oder ähnliches, sodass durch Öffnen und Lesen der Datei die Commit-ID erhalten wurde, und Sie mussten lstat verwenden, um festzustellen, ob Sie "auf einem branch" sind. Dies funktioniert nicht unter Windows und schloss "packing" Branches (.git/packed-refs) aus, daher die Änderung, um stattdessen ref: zu verwenden.

[3] Die Begriffe "erwartet" und "nicht erwartet" sollten Sie dazu bringen, zu fragen: erwartet von wem? Git selbst hat kein Problem damit, dass git-Benutzer Tags verschieben, es sind die Personen, die git verwenden (und oft Skripte, die sie schreiben), die davon verwirrt werden. Bewegen Sie also keinen Tag, es sei denn, Sie haben zuerst mit anderen Personen, die das Repository teilen, Rücksprache gehalten.

8voto

CodeWizard Punkte 108377

Um es einfach zu machen:

Wenn ich einem Git-Repo ein Tag hinzufüge, wird es auf alle Branches angewendet oder nur auf den aktuellen?

In Git ist ein Tag einfach ein Alias für eine Commit-ID. Wenn Sie ein Tag hinzufügen, ordnet Git einfach Ihren Tag-Namen (die Tag-Zeichenkette) einer bestimmten Commit-ID zu. Da die Commit-ID für einen bestimmten Branch relevant ist (oder für Branches beim Zusammenführen), ist das Tag nur für diesen Branch relevant (und für jeden, in den es zusammengeführt wurde).

Weitere Informationen finden Sie hier:

http://git-scm.com/book/en/Git-Basics-Tagging#Creating-Tags

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X