En quoi un tag est-il différent d'une branche dans Git? Que dois-je utiliser ici?

616

J'ai du mal à comprendre comment utiliser les balises par rapport aux branches dans.

Je viens de déplacer la version actuelle de notre code de à , et maintenant je vais travailler sur un sous-ensemble de ce code pour une fonctionnalité particulière. Quelques autres développeurs y travailleront également, mais tous les développeurs de notre groupe ne se soucieront pas de cette fonctionnalité. Dois-je créer une branche ou un tag? Dans quelles situations devrais-je utiliser l'un contre l'autre?

Bialecki
la source
4
Depuis que la recherche sur le Web pour savoir comment utiliser la balise git m'a amené à ce lien en premier, j'ajoute qu'il existe une meilleure réponse (à mon humble avis) à propos d'une balise ici: stackoverflow.com/questions/35979642/…
Alexei Martianov

Réponses:

520

Une balise représente une version d'une branche particulière à un moment donné. Une branche représente un thread de développement distinct qui peut s'exécuter simultanément avec d'autres efforts de développement sur la même base de code. Les modifications apportées à une branche peuvent éventuellement être fusionnées dans une autre branche pour les unifier.

Habituellement , vous marquez une version particulière de sorte que vous pouvez le recréer, par exemple, ceci est la version que nous livré à XYZ Corp . Une brancheest plus une stratégie pour fournir des mises à jour en cours sur une version particulière du code tout en continuant à développer dessus. Vous allez créer une branche de la version livrée, continuer le développement sur la ligne principale, mais apporter des corrections de bogues à la branche qui représente la version livrée. Finalement, vous fusionnerez ces corrections de bogues dans la ligne principale. Vous utiliserez souvent à la fois la ramification et le balisage. Vous aurez différentes balises qui peuvent s'appliquer à la fois à la ligne principale et à ses branches marquant des versions particulières (celles livrées aux clients, par exemple) le long de chaque branche que vous souhaitez recréer - pour la livraison, le diagnostic des bogues, etc.

C'est en fait plus compliqué que cela - ou aussi compliqué que vous voulez le faire - mais ces exemples devraient vous donner une idée des différences.

tvanfosson
la source
40
dans son cas, il veut utiliser des branches, peut-être devriez-vous également le noter dans votre réponse;)
knittl
13
AFAIK, les tags ne sont pas uniques par branche. Vous ne pouvez donc pas donner les mêmes noms pour des validations différentes dans des branches distinctes.
MON
5
@MY Certainement pas une mauvaise chose, à mon humble avis. Surtout de la manière décrite par tvanfosson, avoir plus d'une étiquette avec le même nom sur différentes branches pourrait devenir difficile à maintenir. Compte tenu de l'exemple, je pense que si vous pouviez avoir des balises avec le même nom dans différentes branches, cela serait rapidement établi comme une mauvaise pratique. Bon à savoir que vous ne pouvez pas, cependant. Merci mon!
Pivotant
28
Une balise n'est qu'un alias pour un hachage de validation. De la même manière que vous pouvez extraire un commit, git checkout 88c9f229fvous pouvez faire quelque chose comme git checkout your_taget vous extrairez le commit qui était aliasé par la balise.
jterm
6
@jterm, les branches ne sont-elles pas aussi des alias? La seule différence est qu'un alias de branche se redirige automatiquement vers la validation la plus récente de la chaîne.
Viktor Molokostov
529

Du point de vue théorique :

  • les balises sont des noms symboliques pour une révision donnée . Ils pointent toujours vers le même objet (généralement: vers la même révision); ils ne changent pas.
  • les branches sont des noms symboliques pour la ligne de développement . De nouveaux commits sont créés au-dessus de la branche. Le pointeur de branche avance naturellement, pointant vers des commits de plus en plus récents.

Du point de vue technique :

  • les balises résident dans l' refs/tags/espace de noms et peuvent pointer vers des objets de balise ( balises annotées et éventuellement signées GPG) ou directement pour valider un objet (balise légère moins utilisée pour les noms locaux), ou dans de très rares cas même vers un objet arbre ou un objet blob (par exemple, signature GPG ).
  • les branches résident dans l' refs/heads/espace de noms et ne peuvent pointer que pour valider des objets . Le HEADpointeur doit faire référence à une branche (référence symbolique) ou directement à un commit (HEAD détaché ou branche sans nom).
  • les branches de suivi à distance résident dans l' refs/remotes/<remote>/espace de noms et suivent les branches ordinaires dans le référentiel distant <remote>.

Voir aussi la page de manuel de gitglossary :

branche

Une "branche" est une ligne de développement active. Le commit le plus récent sur une branche est appelé la pointe de cette branche. La pointe de la branche est référencée par une tête de branche, qui avance à mesure que le développement supplémentaire se fait sur la branche. Un seul référentiel git peut suivre un nombre arbitraire de branches, mais votre arbre de travail n'est associé qu'à une seule d'entre elles (la branche "actuelle" ou "extraite"), et HEAD pointe vers cette branche.

étiquette

Une référence pointant vers une balise ou un objet commit. Contrairement à une tête, une balise n'est pas modifiée par un commit. Les balises (et non les balises d'objets) sont stockées dans $GIT_DIR/refs/tags/. [...]. Une balise est généralement utilisée pour marquer un point particulier de la chaîne d'ascendance de validation.

objet tag

Un objet contenant une référence pointant vers un autre objet, qui peut contenir un message comme un objet commit. Il peut également contenir une signature (PGP), auquel cas il est appelé "objet balise signé".

Jakub Narębski
la source
36
Question: si vous traitez une branche comme une balise (c'est-à-dire que vous la créez, puis ne la mettez jamais à jour), y a-t-il une vraie différence?
Steve Bennett
30
@SteveBennett absolument. Il contient différentes informations (vous pouvez signer une balise, vous pouvez ajouter une description à une branche). Vous pouvez déplacer une branche (donc même si vous ne la mettez jamais à jour, vous pouvez toujours la rebaser.). Vous ne pouvez pas déplacer une balise (elle est liée à une validation spécifique). Vous pouvez choisir de pousser une branche. Les balises ne sont pas poussées par défaut. Vous ne devriez jamais utiliser l'un pour l'autre (sauf si vous êtes vraiment dans un état d'esprit SVN, auquel cas vous devez "désapprendre" si vite si vous voulez continuer avec git).
VonC
19
@SteveBennett: Il y a une différence entre la façon dont Git traite les branches et la façon dont il traite les tags. Outre ce que VonC a dit, vous ne pouvez pas faire avancer la balise par erreur: " git checkout <tag>" générerait une branche anonyme sans nom (appelée "tête détachée") et sélectionnerait l' état de la balise. La création d'un nouveau commit le fait sur cette branche sans nom et ne change pas vers quel point pointe.
Jakub Narębski
60
OMI, les branches sont des chronologies séparées (monde parallèle) et les balises sont des moments spécifiques d'une chronologie.
Eonil
25
Personne ici ne l'a encore mentionné mais vous pouvez utiliser une balise comme point de départ pour créer une branche:git checkout -b <branch name> <tag name>
143

Si vous considérez votre référentiel comme un livre qui relate les progrès de votre projet ...

Branches

Vous pouvez considérer une branche comme l'un de ces signets collants :

entrez la description de l'image ici

Un tout nouveau référentiel n'en a qu'un (appelé master), qui se déplace automatiquement vers la dernière page (pensez commit ) que vous avez écrite. Cependant, vous êtes libre de créer et d'utiliser plus de signets, afin de marquer d'autres points d'intérêt dans le livre, afin que vous puissiez y revenir rapidement.

En outre, vous pouvez toujours déplacer un signet particulier vers une autre page du livre (en utilisant git-reset, par exemple); les points d'intérêt varient généralement dans le temps.

Mots clés

Vous pouvez considérer les balises comme des en- têtes de chapitre .

signets

Il peut contenir un titre (pensez aux balises annotées ) ou non. Une étiquette est similaire mais différente d'une branche, en ce sens qu'elle marque un point d' intérêt historique dans le livre. Pour conserver son aspect historique, une fois que vous avez partagé une balise (c'est-à-dire que vous l'avez poussée vers une télécommande partagée), vous n'êtes pas censé la déplacer vers un autre endroit du livre.

jub0bs
la source
16
J'imagine qu'une branche serait un livre, et les signets sont des balises. Vous pouvez continuer à écrire un livre, mais vous ne pouvez pas le modifier. La balise n'est qu'un moment fixe dans le livre.
Mārtiņš Briedis
5
@Jubobs J'ai aimé l'explication de la branche comme ligne de développement. Un livre serait une branche. Vous pouvez commencer un nouveau livre en fonction de l'endroit où a quitté la branche principale. Vous pouvez les écrire parallèlement, puis essayer de les fusionner avec un seul livre / une seule branche.
Mārtiņš Briedis
2
@ MārtiņšBriedis Je comprends la façon dont vous aimez penser à une branche, mais je trouve que, dans Git, c'est en fait trompeur. Voir stackoverflow.com/questions/25068543/…
jub0bs
2
celui-ci est vraiment une réponse pour gagner du temps
Ali Foroughi
2
Si vous commencez à écrire un livre et que vous avez les 50 premières pages, vous pouvez le copier (créer une nouvelle branche à partir de celui-ci) et continuer à écrire deux livres simultanément (ou donner la copie du livre à un autre écrivain - développeur) et enfin vous pouvez fusionner le les modifications de l'autre livre à votre livre.
barell
42

Ce que vous devez comprendre, venant de CVS, c'est que vous ne créez plus de répertoires lors de la configuration d'une branche.
Plus de "tag collant" (qui peut être appliqué à un seul fichier), ni de "tag de branche".
La branche et les balises sont deux objets différents dans Git, et ils s'appliquent toujours au tout repo.

Vous n'auriez plus (avec SVN cette fois) à structurer explicitement votre référentiel avec:

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

Cette structure vient du fait que CVS est un système de révision et non un système de version (voir Contrôle de code source vs Contrôle de révision? ).
Cela signifie que les branches sont émulées via des balises pour CVS, des copies de répertoires pour SVN.

Votre question est logique si vous avez l'habitude de retirer une balise et de commencer à y travailler .
Ce que vous ne devriez pas;)
Une balise est censée représenter un contenu immuable , utilisé uniquement pour y accéder avec la garantie d'obtenir le même contenu à chaque fois.

Dans Git, l'historique des révisions est une série de commits, formant un graphique.
Une branche est un chemin de ce graphique

x--x--x--x--x # one branch
    \ 
     --y----y # another branch
       1.1
        ^
        |
        # a tag pointing to a commit
  • Si vous extrayez une balise, vous devrez créer une branche pour commencer à travailler à partir de celle-ci.
  • Si vous extrayez une branche, vous verrez directement le dernier commit ('HEAD') de cette branche.

Voir la réponse de Jakub Narębski pour toutes les détails techniques, mais franchement, à ce stade, vous n'avez pas (encore) tous les détails;)

Le point principal est: une balise étant un simple pointeur vers une validation, vous ne pourrez jamais modifier son contenu. Vous avez besoin d'une succursale.


Dans votre cas, chaque développeur travaillant sur une fonctionnalité spécifique:

  • doivent créer leur propre branche dans leur référentiel respectif
  • suivre les branches depuis les référentiels de leurs collègues (celui qui travaille sur la même fonctionnalité)
  • tirer / pousser pour partager votre travail avec vos pairs.

Au lieu de suivre directement les branches de vos collègues, vous ne pouvez suivre que la branche d'un référentiel central "officiel" vers lequel chacun pousse son travail afin d'intégrer et de partager le travail de chacun pour cette fonctionnalité particulière.

VonC
la source
1
merci d'avoir clarifié le fonctionnement des branches et des balises :) je ne serais pas en mesure de le comprendre sans votre exemple.
ufk
3
@VonC: Je pense que vous voulez dire "SVN" dans votre réponse et non "CVS". CVS n'a pas la structure du répertoire; SVN le fait. En fait, le balisage dans git me rappelle beaucoup plus le balisage dans RCS / CVS que le balisage dans SVN (où tag == branche dégénérée).
Chris Cleeland
1
@ChrisCleeland bon point. J'ai essayé de séparer un peu plus de points CVS et SVN dans la réponse (modifiée).
VonC
37

Les branches sont en bois et poussent à partir du tronc de l'arbre. Les étiquettes sont faites de papier (dérivé du bois) et sont suspendues comme des décorations de Noël à divers endroits de l'arbre.

Votre projet est l'arborescence et votre fonctionnalité qui sera ajoutée au projet se développera sur une branche. La réponse est branche.

Jason
la source
3
amour pour l'analogie
doz87
16

Il semble que la meilleure façon d'expliquer est que les balises agissent comme des branches en lecture seule. Vous pouvez utiliser une branche comme balise, mais vous pouvez la mettre à jour par inadvertance avec de nouveaux commits. Les balises sont garanties pour pointer vers le même commit tant qu'elles existent.

Vassili Gorshkov
la source
11
Les balises sont garanties pour pointer vers le même commit tant qu'elles existent. Pas tout à fait vrai. Vous pouvez réellement déplacer une balise avec git tag -f.
jub0bs
14

Les balises peuvent être signées ou non signées ; les succursales ne sont jamais signées.

Les balises signées ne peuvent jamais se déplacer car elles sont liées cryptographiquement (avec une signature) à un commit particulier. Les balises non signées ne sont pas liées et il est possible de les déplacer (mais le déplacement de balises n'est pas un cas d'utilisation normal).

Les branches peuvent non seulement passer à un autre engagement mais devrait le faire. Vous devez utiliser une succursale pour votre projet de développement local. Cela n'a aucun sens de valider le travail dans un référentiel Git "sur une balise".

Greg Hewgill
la source
12

J'aime penser aux branches comme où vous allez , aux balises comme où vous avez été .

Une balise ressemble à un signet d'un point important particulier dans le passé, comme une version.

Alors qu'une branche est un chemin particulier, le projet descend, et donc le marqueur de branche avance avec vous. Lorsque vous avez terminé, vous fusionnez / supprimez la branche (c'est-à-dire le marqueur). Bien sûr, à ce stade, vous pouvez choisir de baliser ce commit.

Gazzer
la source
10

La parabole Git explique comment un DVCS typique est créé et pourquoi leurs créateurs ont fait ce qu'ils ont fait. En outre, vous voudrez peut-être jeter un œil à Git for Computer Scientist ; il explique ce que fait chaque type d'objet dans Git, y compris les branches et les balises.

Bombe
la source
6

Une balise est utilisée pour marquer une version, plus précisément elle fait référence à un point dans le temps sur une branche. Une branche est généralement utilisée pour ajouter des fonctionnalités à un projet.

Numéro45
la source
4

Facile:

Les balises doivent toujours pointer vers la même version d'un projet, tandis que les têtes doivent progresser à mesure que le développement progresse.

Manuel de l'utilisateur Git

Bar Horing
la source
4

la réponse simple est:

branche: le pointeur de branche actuel se déplace à chaque validation dans le référentiel

mais

tag: le commit sur lequel pointe un tag ne change pas, en fait le tag est un instantané de ce commit.

jsina
la source