Wie unterscheidet sich ein Tag von einem Zweig in Git? Welches soll ich hier verwenden?

616

Ich habe einige Schwierigkeiten zu verstehen, wie Tags im Vergleich zu Zweigen in verwendet werden.

Ich habe gerade die aktuelle Version unseres Codes von verschoben zu und jetzt werde ich an einer Teilmenge dieses Codes für eine bestimmte Funktion arbeiten. Einige andere Entwickler werden ebenfalls daran arbeiten, aber nicht alle Entwickler in unserer Gruppe werden sich um diese Funktion kümmern. Soll ich einen Zweig oder ein Tag erstellen? In welchen Situationen sollte ich eins gegen das andere verwenden?

Bialecki
quelle
4
Da mich die Websuche zur Verwendung des Git-Tags zuerst zu diesem Link geführt hat, füge ich hinzu, dass es hier eine bessere (IMHO) Antwort zu einem Tag gibt: stackoverflow.com/questions/35979642/…
Alexei Martianov

Antworten:

520

Ein Tag repräsentiert eine Version eines bestimmten Zweigs zu einem bestimmten Zeitpunkt. Ein Zweig stellt einen separaten Entwicklungsthread dar, der möglicherweise gleichzeitig mit anderen Entwicklungsbemühungen auf derselben Codebasis ausgeführt wird. Änderungen an einem Zweig können eventuell wieder in einem anderen Zweig zusammengeführt werden, um sie zu vereinheitlichen.

Normalerweise markieren Sie eine bestimmte Version, damit Sie sie neu erstellen können. Dies ist beispielsweise die Version, die wir an XYZ Corp geliefert haben . Ein Zweigist eher eine Strategie, um fortlaufende Updates für eine bestimmte Version des Codes bereitzustellen und gleichzeitig die Entwicklung fortzusetzen. Sie werden einen Zweig der gelieferten Version erstellen, die Entwicklung in der Hauptzeile fortsetzen, aber Fehlerbehebungen an dem Zweig vornehmen, der die gelieferte Version darstellt. Schließlich werden Sie diese Fehlerkorrekturen wieder in der Hauptzeile zusammenführen. Oft verwenden Sie sowohl Verzweigung als auch Markierung zusammen. Sie haben verschiedene Tags, die sowohl für die Hauptzeile als auch für ihre Zweige gelten können und bestimmte Versionen (z. B. die an Kunden gelieferten) in jedem Zweig kennzeichnen, den Sie möglicherweise neu erstellen möchten - für Zustellung, Fehlerdiagnose usw.

Es ist tatsächlich komplizierter als das - oder so kompliziert, wie Sie es machen möchten -, aber diese Beispiele sollten Ihnen eine Vorstellung von den Unterschieden geben.

Tvanfosson
quelle
40
in seinem Fall möchte er Zweige verwenden, vielleicht sollten Sie dies auch in Ihrer Antwort vermerken;)
knittl
13
AFAIK, Tags sind nicht eindeutig pro Zweig. Sie können also nicht dieselben Namen für verschiedene Commits in separaten Zweigen angeben.
MEIN
5
@MY Sicherlich keine schlechte Sache, IMHO. Insbesondere auf die von tvanfosson beschriebene Weise kann es schwierig werden, mehr als ein Tag mit demselben Namen in verschiedenen Zweigen zu haben. In Anbetracht des Beispiels würde ich denken, dass Tags mit demselben Namen in verschiedenen Zweigen schnell als schlechte Praxis etabliert werden könnten . Gut zu wissen, dass Sie das nicht können. Danke MEIN!
Wirbel
28
Ein Tag ist nur ein Alias ​​für einen Commit-Hash. Genauso wie Sie ein Commit mit auschecken git checkout 88c9f229fkönnen, können Sie so etwas wie tun git checkout your_tagund Sie werden das Commit auschecken, das vom Tag als Alias ​​verwendet wurde.
jterm
6
@jterm, sind nicht auch Zweig-Aliase? Der einzige Unterschied besteht darin, dass sich ein Verzweigungsalias automatisch auf das letzte Commit in der Kette neu verweist.
Viktor Molokostov
529

Aus theoretischer Sicht:

  • Tags sind symbolische Namen für eine bestimmte Revision . Sie zeigen immer auf dasselbe Objekt (normalerweise: auf dieselbe Revision); sie ändern sich nicht.
  • Zweige sind symbolische Namen für Entwicklungslinien . Neue Commits werden über dem Zweig erstellt. Der Verzweigungszeiger bewegt sich natürlich weiter und zeigt auf immer neuere Commits.

Aus technischer Sicht:

  • Tags befinden sich im refs/tags/Namespace und können auf Tag-Objekte (mit Anmerkungen versehene und optional mit GPG signierte Tags) oder direkt auf Commit-Objekte (weniger verwendetes leichtes Tag für lokale Namen) oder in sehr seltenen Fällen sogar auf Baumobjekte oder Blob-Objekte (z. B. GPG-Signatur) verweisen ).
  • Zweige befinden sich im refs/heads/Namespace und können nur auf Commit-Objekte verweisen . Der HEADZeiger muss sich auf einen Zweig (symbolische Referenz) oder direkt auf einen Commit (losgelöster HEAD oder unbenannter Zweig) beziehen.
  • Remote-Tracking-Zweige befinden sich im refs/remotes/<remote>/Namespace und folgen normalen Zweigen im Remote-Repository <remote>.

Siehe auch gitglossary manpage:

Ast

Ein "Zweig" ist eine aktive Entwicklungslinie. Das letzte Commit für einen Zweig wird als Spitze dieses Zweigs bezeichnet. Die Spitze des Zweigs wird von einem Zweigkopf referenziert, der sich vorwärts bewegt, wenn zusätzliche Entwicklung am Zweig durchgeführt wird. Ein einzelnes Git-Repository kann eine beliebige Anzahl von Zweigen verfolgen, aber Ihr Arbeitsbaum ist nur einem von ihnen zugeordnet (dem "aktuellen" oder "ausgecheckten" Zweig), und HEAD zeigt auf diesen Zweig.

Etikett

Ein Verweis, der auf ein Tag oder ein Commit-Objekt zeigt. Im Gegensatz zu einem Kopf wird ein Tag nicht durch ein Commit geändert. Tags (keine Tag-Objekte) werden in gespeichert $GIT_DIR/refs/tags/. [...]. Ein Tag wird normalerweise verwendet, um einen bestimmten Punkt in der Commit-Abstammungskette zu markieren.

Tag-Objekt

Ein Objekt, das einen Verweis enthält, der auf ein anderes Objekt verweist, das wie ein Festschreibungsobjekt eine Nachricht enthalten kann. Es kann auch eine (PGP) Signatur enthalten. In diesem Fall wird es als "signiertes Tag-Objekt" bezeichnet.

Jakub Narębski
quelle
36
Frage: Wenn Sie einen Zweig wie ein Tag behandeln (dh Sie erstellen ihn und aktualisieren ihn dann nie), gibt es einen wirklichen Unterschied?
Steve Bennett
30
@SteveBennett absolut. Es enthält verschiedene Informationen (Sie können ein Tag signieren, Sie können einer Zweigstelle eine Beschreibung hinzufügen). Sie können einen Zweig verschieben (auch wenn Sie ihn nie aktualisieren, können Sie ihn dennoch neu starten). Sie können ein Tag nicht verschieben (es ist mit einem bestimmten Commit verknüpft). Sie können einen Zweig verschieben. Tags werden standardmäßig nicht gepusht. Sie sollten niemals eins für das andere verwenden (es sei denn, Sie sind wirklich in einer SVN-Denkweise. In diesem Fall müssen Sie so schnell "lernen", wenn Sie mit git weitermachen möchten).
VonC
19
@SteveBennett: Es gibt einen Unterschied, wie Git Zweige behandelt, und wie Tags behandelt werden. Abgesehen von dem, was VonC gesagt hat, können Sie das Tag nicht versehentlich vorrücken: " git checkout <tag>" würde einen anonymen unbenannten Zweig (so genannter "losgelöster HEAD") erzeugen und den Status des Tags auswählen . Das Erstellen eines neuen Commits erfolgt in diesem unbenannten Zweig und ändert nicht, auf welches Tag verweist.
Jakub Narębski
60
IMO, Zweige sind getrennte Zeitleisten (Parallelwelt), und Tags sind bestimmte Momente auf einer Zeitachse.
Eonil
25
Niemand hier hat es bisher erwähnt, aber Sie können ein Tag als Punkt verwenden, um einen Zweig zu starten:git checkout -b <branch name> <tag name>
143

Wenn Sie sich Ihr Repository als ein Buch vorstellen, das den Fortschritt Ihres Projekts aufzeichnet ...

Geäst

Sie können sich einen Zweig als eines dieser klebrigen Lesezeichen vorstellen :

Geben Sie hier die Bildbeschreibung ein

In einem brandneuen Repository gibt es nur eines (aufgerufen master), das automatisch zur neuesten Seite (Think Commit ) wechselt, die Sie geschrieben haben. Es steht Ihnen jedoch frei, weitere Lesezeichen zu erstellen und zu verwenden, um andere interessante Punkte im Buch zu markieren, sodass Sie schnell zu ihnen zurückkehren können.

Sie können ein bestimmtes Lesezeichen auch jederzeit auf eine andere Seite des Buches verschieben ( git-resetz. B. mithilfe von). Punkte von Interesse variieren normalerweise im Laufe der Zeit.

Stichworte

Sie können sich Tags als Kapitelüberschriften vorstellen .

Lesezeichen

Es kann einen Titel enthalten (denken Sie an kommentierte Tags ) oder nicht. Ein Tag ist ähnlich, aber anders als ein Zweig, da es einen Punkt von historischem Interesse im Buch markiert . Um den historischen Aspekt beizubehalten, sollten Sie ein freigegebenes Tag (dh das Verschieben auf eine freigegebene Fernbedienung) nicht an eine andere Stelle im Buch verschieben.

jub0bs
quelle
16
Ich würde mir vorstellen, dass ein Zweig ein Buch ist und Lesezeichen Tags sind. Sie können ein Buch weiter schreiben, aber nicht bearbeiten. Tag ist nur ein fester Moment im Buch.
Mārtiņš Briedis
5
@Jubobs Ich mochte die Erklärung des Zweigs als Entwicklungslinie. Ein Buch wäre ein Zweig. Sie können ein neues Buch basierend auf der Stelle beginnen, an der der Hauptzweig verlassen wurde. Sie können sie parallel schreiben und dann versuchen, sie zu einem Buch / Zweig zusammenzuführen.
Mārtiņš Briedis
2
@ MārtiņšBriedis Ich verstehe, wie Sie gerne über einen Zweig denken, aber ich finde, dass das in Git tatsächlich irreführend ist. Siehe stackoverflow.com/questions/25068543/…
jub0bs
2
Dies ist wirklich eine zeitsparende Antwort
Ali Foroughi
2
Wenn Sie mit dem Schreiben eines Buches beginnen und die ersten 50 Seiten haben, können Sie es kopieren (einen neuen Zweig daraus erstellen) und zwei Bücher gleichzeitig weiter schreiben (oder die Buchkopie einem anderen Autor - Entwickler geben), und schließlich können Sie das zusammenführen wechselt vom anderen Buch zu Ihrem Buch.
Barell
42

Aus CVS geht hervor, dass Sie beim Einrichten eines Zweigs keine Verzeichnisse mehr erstellen .
Kein "Sticky Tag" (das nur auf eine Datei angewendet werden kann) oder "Branch Tag" mehr.
Branch und Tags sind zwei verschiedene Objekte in Git und gelten immer für das All- Repo.

Sie müssten Ihr Repository nicht mehr (diesmal mit SVN) explizit strukturieren mit:

branches
   myFirstBranch
     myProject
       mySubDirs
   mySecondBranch
     ...
tags
   myFirstTag
     myProject
       mySubDirs
   mySecondTag
   ...

Diese Struktur beruht auf der Tatsache, dass CVS ein Revisionssystem und kein Versionssystem ist (siehe Quellcodeverwaltung vs. Revisionskontrolle? ).
Das bedeutet, dass Zweige über Tags für CVS und Verzeichniskopien für SVN emuliert werden.

Ihre Frage macht Sinn, wenn Sie es gewohnt sind, ein Tag auszuchecken und damit zu arbeiten .
Was Sie nicht sollten;)
Ein Tag soll einen unveränderlichen Inhalt darstellen, der nur verwendet wird, um darauf zuzugreifen, mit der Garantie, jedes Mal denselben Inhalt zu erhalten.

In Git besteht die Geschichte der Revisionen aus einer Reihe von Commits, die ein Diagramm bilden.
Ein Zweig ist ein Pfad dieses Graphen

x--x--x--x--x # one branch
    \ 
     --y----y # another branch
       1.1
        ^
        |
        # a tag pointing to a commit
  • Wenn Sie ein Tag auschecken, müssen Sie einen Zweig erstellen, um damit arbeiten zu können.
  • Wenn Sie einen Zweig auschecken, wird direkt das letzte Commit ('HEAD') dieses Zweigs angezeigt.

Siehe Jakub Narębskis Antwort für alle technischen Details, aber ehrlich gesagt, an dieser Stelle brauchen Sie (noch) nicht alle Details;)

Der Hauptpunkt ist: Da ein Tag ein einfacher Zeiger auf ein Commit ist, können Sie dessen Inhalt niemals ändern. Du brauchst einen Zweig.


In Ihrem Fall arbeitet jeder Entwickler an einer bestimmten Funktion:

  • sollten einen eigenen Zweig in ihrem jeweiligen Repository erstellen
  • Verfolgen von Zweigen aus den Repositories ihrer Kollegen (die an derselben Funktion arbeiten)
  • Ziehen / Schieben, um Ihre Arbeit mit Ihren Kollegen zu teilen.

Anstatt die Zweige Ihrer Kollegen direkt zu verfolgen, können Sie nur den Zweig eines "offiziellen" zentralen Repositorys verfolgen, in das jeder seine Arbeit überträgt, um die Arbeit aller für diese bestimmte Funktion zu integrieren und zu teilen.

VonC
quelle
1
Vielen Dank für die Klarstellung, wie Zweige und Tags funktionieren :) Ohne Ihr Beispiel wäre ich nicht in der Lage, es vollständig zu verstehen.
Ufk
3
@VonC: Ich denke du meinst "SVN" in deiner Antwort und nicht "CVS". CVS hat keine Verzeichnisstruktur. SVN tut. Tatsächlich erinnert mich das Markieren in git viel mehr an das Markieren in RCS / CVS als an das Markieren in SVN (wobei tag == degenerate branch).
Chris Cleeland
1
@ ChrisCleeland guter Punkt. Ich habe versucht, ein bisschen mehr CVS- und SVN-Punkte in der (bearbeiteten) Antwort zu trennen.
VonC
37

Zweige bestehen aus Holz und wachsen aus dem Stamm des Baumes. Tags bestehen aus Papier (Derivat von Holz) und hängen wie Weihnachtsschmuck an verschiedenen Stellen im Baum.

Ihr Projekt ist der Baum, und Ihre Funktion, die dem Projekt hinzugefügt wird, wächst auf einem Zweig. Die Antwort lautet Zweig.

Jason
quelle
3
Liebe zur Analogie
doz87
16

Es sieht so aus, als ob der beste Weg zu erklären ist, dass Tags als schreibgeschützte Zweige fungieren. Sie können einen Zweig als Tag verwenden, ihn jedoch möglicherweise versehentlich mit neuen Commits aktualisieren. Tags verweisen garantiert auf dasselbe Commit, solange sie vorhanden sind.

Vassili Gorshkov
quelle
11
Tags verweisen garantiert auf dasselbe Commit, solange sie vorhanden sind. Nicht ganz richtig. Sie können ein Tag tatsächlich mit verschieben git tag -f.
jub0bs
14

Tags können entweder signiert oder nicht signiert sein . Filialen werden nie signiert.

Signierte Tags können niemals verschoben werden, da sie kryptografisch (mit einer Signatur) an ein bestimmtes Commit gebunden sind. Nicht signierte Tags sind nicht gebunden und können verschoben werden (das Verschieben von Tags ist jedoch kein normaler Anwendungsfall).

Zweige können nicht nur zu einem anderen Commit wechseln, sondern dies wird auch erwartet . Sie sollten einen Zweig für Ihr lokales Entwicklungsprojekt verwenden. Es ist nicht ganz sinnvoll, die Arbeit "auf einem Tag" in ein Git-Repository zu übertragen.

Greg Hewgill
quelle
12

Ich stelle mir Zweige gerne als den Ort vor, an den Sie gehen , Tags als den Ort, an dem Sie gewesen sind .

Ein Tag fühlt sich wie ein Lesezeichen für einen bestimmten wichtigen Punkt in der Vergangenheit an, z. B. eine Versionsversion.

Während ein Zweig ein bestimmter Pfad ist, geht das Projekt nach unten, und daher rückt der Zweigmarker mit Ihnen vor. Wenn Sie fertig sind, führen Sie den Zweig (dh die Markierung) zusammen / löschen ihn. An diesem Punkt können Sie natürlich festlegen, dass das Commit markiert werden soll.

Gazzer
quelle
10

Das Git-Gleichnis erklärt, wie ein typisches DVCS erstellt wird und warum ihre Entwickler das getan haben, was sie getan haben. Vielleicht möchten Sie auch einen Blick auf Git for Computer Scientist werfen . Es wird erklärt, was jeder Objekttyp in Git tut, einschließlich Zweigen und Tags.

Bombe
quelle
6

Ein Tag wird zum Markieren einer Version verwendet, genauer gesagt, es verweist auf einen Zeitpunkt in einem Zweig. Ein Zweig wird normalerweise verwendet, um einem Projekt Features hinzuzufügen.

Nummer 45
quelle
4

einfach:

Von Tags wird erwartet, dass sie immer auf dieselbe Version eines Projekts verweisen, während von den Köpfen erwartet wird, dass sie im Verlauf der Entwicklung voranschreiten.

Git Benutzerhandbuch

Bar Horing
quelle
4

Die einfache Antwort lautet:

branch: Der aktuelle Branch-Zeiger wird bei jedem Commit in das Repository verschoben

aber

Tag: Das Commit, auf das ein Tag zeigt, ändert sich nicht. Tatsächlich ist das Tag eine Momentaufnahme dieses Commits.

jsina
quelle