Qual a diferença entre uma tag e uma ramificação no Git? Qual devo usar aqui?

616

Estou com dificuldades para entender como usar tags versus ramificações em.

Acabei de mudar a versão atual do nosso código de para , e agora vou trabalhar em um subconjunto desse código para um recurso específico. Alguns outros desenvolvedores também trabalharão nisso, mas nem todos os desenvolvedores do nosso grupo se importarão com esse recurso. Devo estar criando uma ramificação ou uma tag? Em que situações devo usar um contra o outro?

Bialecki
fonte
4
Como a pesquisa na web sobre como usar a tag git me levou a esse link primeiro, adiciono que há uma resposta melhor (IMHO) sobre uma tag aqui: stackoverflow.com/questions/35979642/… #
Alexei Martianov

Respostas:

520

Uma tag representa uma versão de um ramo específico em um momento. Uma ramificação representa um segmento de desenvolvimento separado que pode ser executado simultaneamente com outros esforços de desenvolvimento na mesma base de código. Alterações em uma ramificação podem eventualmente ser mescladas novamente em outra ramificação para unificá-las.

Normalmente você vai marcar uma versão específica para que você possa recriá-lo, por exemplo, esta é a versão que nós lançamos a XYZ Corp . Um ramoé mais uma estratégia para fornecer atualizações contínuas em uma versão específica do código, enquanto continua desenvolvendo o mesmo. Você fará uma ramificação da versão entregue, continuará o desenvolvimento na linha principal, mas fará correções de bugs na ramificação que representa a versão entregue. Eventualmente, você mesclará essas correções de erros novamente na linha principal. Geralmente, você usa ramificação e marcação juntas. Você terá várias tags que podem ser aplicadas tanto à linha principal quanto às suas filiais, marcando versões específicas (aquelas entregues aos clientes, por exemplo) ao longo de cada filial que você deseja recriar - para entrega, diagnóstico de erros etc.

Na verdade, é mais complicado do que isso - ou tão complicado quanto você deseja -, mas esses exemplos devem lhe dar uma idéia das diferenças.

tvanfosson
fonte
40
no caso dele, ele quer usar ramos, talvez você também deve observar isso em sua resposta;)
knittl
13
AFAIK, as tags não são exclusivas por filial. Portanto, você não pode dar os mesmos nomes para confirmações diferentes em ramificações separadas.
MY
5
@ MY Certamente não é uma coisa ruim, IMHO. Especialmente da maneira descrita por tvanfosson, ter mais de uma tag com o mesmo nome em diferentes ramos pode se tornar difícil de manter. Dado o exemplo, eu pensaria que, se você pudesse ter tags com o mesmo nome em diferentes ramificações, isso seria rapidamente estabelecido como uma má prática. É bom saber que você não pode, no entanto. Obrigado meu!
Swivel
28
Uma tag é apenas um alias para um hash de confirmação. Da mesma forma que você pode fazer o check-out de um commit, git checkout 88c9f229fvocê pode fazer algo como git checkout your_tage fará o check-out do commit que foi aliasado pela tag.
jterm
6
@ jterm, não são aliases de ramos também? A única diferença é que um alias de ramificação automaticamente se autodenomina para o commit mais recente da cadeia.
Viktor Molokostov
529

Do ponto de vista teórico :

  • tags são nomes simbólicos para uma determinada revisão . Eles sempre apontam para o mesmo objeto (geralmente: para a mesma revisão); eles não mudam.
  • branches são nomes simbólicos para a linha de desenvolvimento . Novas confirmações são criadas na parte superior da ramificação. O ponteiro de ramificação avança naturalmente, apontando para confirmações cada vez mais recentes.

Do ponto de vista técnico :

  • as tags residem no refs/tags/namespace e podem apontar para marcar objetos ( tags anotadas e opcionalmente assinadas pelo GPG) ou diretamente para confirmar o objeto (tag leve menos usada para nomes locais) ou, em casos muito raros, mesmo para o objeto em árvore ou o objeto blob (por exemplo, assinatura GPG )
  • ramificações residem no refs/heads/espaço para nome e podem apontar apenas para confirmar objetos . O HEADponteiro deve se referir a uma ramificação (referência simbólica) ou diretamente a uma confirmação (HEAD desanexado ou ramificação sem nome).
  • As ramificações de rastreamento remoto residem no refs/remotes/<remote>/espaço para nome e seguem ramificações comuns no repositório remoto <remote>.

Veja também a página de manual do gitglossary :

ramo

Um "ramo" é uma linha de desenvolvimento ativa. A confirmação mais recente em uma ramificação é referida como a ponta dessa ramificação. A ponta do ramo é referenciada por uma cabeça de ramo, que avança à medida que o desenvolvimento adicional é feito no ramo. Um único repositório git pode rastrear um número arbitrário de ramificações, mas sua árvore de trabalho está associada a apenas uma delas (a ramificação "atual" ou "com saída") e o HEAD aponta para essa ramificação.

tag

Um árbitro apontando para uma tag ou objeto de confirmação. Ao contrário de uma cabeça, uma tag não é alterada por uma confirmação. Tags (não objetos de tag) são armazenadas em $GIT_DIR/refs/tags/. [...] Uma tag é normalmente usada para marcar um ponto específico na cadeia de ascendência de confirmação.

objeto de tag

Um objeto que contém um ref apontando para outro objeto, que pode conter uma mensagem como um objeto de confirmação. Também pode conter uma assinatura (PGP); nesse caso, é chamado de "objeto de tag assinado".

Jakub Narębski
fonte
36
Pergunta: se você trata um ramo como uma tag (ou seja, você o cria e nunca o atualiza), existe alguma diferença real?
Steve Bennett
30
@SteveBennett absolutamente. Contém informações diferentes (você pode assinar uma etiqueta, adicionar uma descrição a uma filial). Você pode mover uma ramificação (mesmo que você nunca a atualize, ainda poderá refazê-la). Você não pode mover uma tag (ela está vinculada a um commit específico). Você pode optar por enviar um ramo. As tags não são enviadas por padrão. Você nunca deve usar um para o outro (a menos que esteja realmente na mentalidade de SVN, nesse caso, você precisará "desaprender" tão rápido se quiser continuar com o git).
VonC
19
@SteveBennett: Há uma diferença em como o Git trata ramos versus como trata as tags. Além do que o VonC disse, você não pode avançar a tag por engano: " git checkout <tag>" geraria uma ramificação anônima e sem nome (chamada 'HEAD desanexada') e selecionaria o estado da tag. A criação de uma nova confirmação o faz nesta ramificação sem nome e não altera para qual marca o apontar.
Jakub Narębski
60
Na IMO, as ramificações são linhas de tempo separadas (mundo paralelo) e as tags são momentos específicos em uma linha do tempo.
Eonil
25
Ninguém aqui mencionou ainda, mas você pode usar uma tag como ponto para iniciar uma ramificação:git checkout -b <branch name> <tag name>
143

Se você pensa no seu repositório como um livro que registra o progresso do seu projeto ...

Ramos

Você pode pensar em uma ramificação como um desses favoritos :

insira a descrição da imagem aqui

Um novo repositório possui apenas um desses (chamado master), que se move automaticamente para a página mais recente (pense em commit ) que você escreveu. No entanto, você pode criar e usar mais indicadores para marcar outros pontos de interesse no livro, para poder retornar rapidamente a eles.

Além disso, você sempre pode mover um marcador específico para outra página do livro (usando git-reset, por exemplo); os pontos de interesse geralmente variam com o tempo.

Tag

Você pode pensar em tags como títulos de capítulo .

favoritos

Pode conter um título (pense em tags anotadas ) ou não. Uma etiqueta é semelhante, mas diferente de uma ramificação, na medida em que marca um ponto de interesse histórico no livro. Para manter seu aspecto histórico, depois de compartilhar uma tag (ou seja, empurrá-la para um controle remoto compartilhado), você não deve movê-la para outro lugar do livro.

jub0bs
fonte
16
Imagino que um ramo seria um livro, e os marcadores são tags. Você pode continuar escrevendo um livro, mas não pode editá-lo. Tag é apenas um momento fixo no livro.
Mari Briedis
5
@ Jubobs Gostei da explicação do ramo como uma linha de desenvolvimento. Um livro seria um ramo. Você pode iniciar um novo livro com base no local em que deixou a ramificação principal. Você pode escrevê-los paralelamente e tentar mesclar um livro / filial.
Mari Briedis
2
@ MārtiņšBriedis Entendo como você gosta de pensar em um ramo, mas acho que, no Git, isso é realmente enganador. Veja stackoverflow.com/questions/25068543/…
jub0bs
2
este é realmente uma resposta poupança de tempo
Ali Foroughi
2
Se você começar a escrever um livro e tiver as primeiras 50 páginas, poderá copiá-lo (criar uma nova ramificação a partir dele) e continuar escrevendo dois livros simultaneamente (ou fornecer a cópia do livro para outro escritor - desenvolvedor) e, finalmente, poderá mesclar o muda do outro livro para o seu livro.
2228 Barell
42

O que você precisa perceber, vindo do CVS, é que você não cria mais diretórios ao configurar uma ramificação.
Chega de "etiqueta adesiva" (que pode ser aplicada a apenas um arquivo) ou "etiqueta de ramificação".
Ramificação e tags são dois objetos diferentes no Git e sempre se aplicam ao repositório all .

Você não precisaria mais (com o SVN dessa vez) estruturar explicitamente seu repositório com:

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

Essa estrutura vem do fato de o CVS ser um sistema de revisão e não um sistema de versão (consulte Controle de origem vs. Controle de revisão? ).
Isso significa que os ramos são emulados através de tags para CVS, cópias de diretório para SVN.

Sua pergunta faz sentido se você estiver acostumado a fazer check-out de uma tag e começar a trabalhar nela .
O que você não deveria;)
Uma tag deve representar um conteúdo imutável , usado apenas para acessá-la com a garantia de obter o mesmo conteúdo sempre.

No Git, o histórico de revisões é uma série de confirmações, formando um gráfico.
Uma ramificação é um caminho desse gráfico

x--x--x--x--x # one branch
    \ 
     --y----y # another branch
       1.1
        ^
        |
        # a tag pointing to a commit
  • Se você fizer check-out de uma tag, precisará criar uma ramificação para começar a trabalhar nela.
  • Se você efetuar o checkout de um ramo, verá diretamente o último commit ('HEAD') desse ramo.

Veja a resposta de Jakub Narębski para todos os detalhes técnicos, mas, francamente, neste momento, você não precisa (ainda) de todos os detalhes;)

O ponto principal é: uma tag sendo um simples ponteiro para um commit, você nunca poderá modificar seu conteúdo. Você precisa de um ramo.


No seu caso, cada desenvolvedor trabalhando em um recurso específico:

  • deve criar sua própria ramificação em seu respectivo repositório
  • rastrear ramificações dos repositórios de seus colegas (aquele que trabalha no mesmo recurso)
  • puxar / empurrar para compartilhar seu trabalho com seus colegas.

Em vez de rastrear diretamente as ramificações de seus colegas, você pode rastrear apenas a ramificação de um repositório central "oficial" no qual todos enviam seu trabalho para integrar e compartilhar o trabalho de todos para esse recurso específico.

VonC
fonte
1
obrigado por esclarecer como os ramos e as tags funcionam :) eu não seria capaz de entendê-lo completamente sem o seu exemplo.
Ufk
3
@VonC: Eu acho que você quer dizer "SVN" na sua resposta e não "CVS". O CVS não possui a estrutura de diretórios; SVN faz. De fato, a marcação no git me lembra muito mais a marcação no RCS / CVS do que a marcação no SVN (onde tag == degenerate branch).
Chris Cleeland
1
@ChrisCleeland good point. Tentei separar um pouco mais de pontos CVS e SVN na resposta (editada).
VonC 16/08/12
37

Os galhos são feitos de madeira e crescem a partir do tronco da árvore. As etiquetas são feitas de papel (derivado da madeira) e penduradas como enfeites de natal de vários lugares da árvore.

Seu projeto é a árvore e seu recurso que será adicionado ao projeto aumentará em uma ramificação. A resposta é ramo.

Jason
fonte
3
amor pela analogia
doz87
16

Parece que a melhor maneira de explicar é que as tags agem como ramos somente leitura. Você pode usar uma ramificação como tag, mas pode inadvertidamente atualizá-la com novas confirmações. As tags são garantidas para apontar para o mesmo commit, desde que existam.

Vassili Gorshkov
fonte
11
As tags são garantidas para apontar para o mesmo commit, desde que existam. Não é completamente verdade. Você pode realmente mover uma tag com git tag -f.
Jb0bs
14

As tags podem ser assinadas ou não assinadas ; ramos nunca são assinados.

As tags assinadas nunca podem ser movidas porque estão vinculadas criptograficamente (com uma assinatura) a um commit específico. Tags não assinadas não são vinculadas e é possível movê-las (mas mover tags não é um caso de uso normal).

As ramificações podem não apenas passar para um commit diferente, mas também devem fazê-lo. Você deve usar uma ramificação para o seu projeto de desenvolvimento local. Não faz muito sentido comprometer o trabalho em um repositório Git "em uma tag".

Greg Hewgill
fonte
12

Eu gosto de pensar em galhos como onde você está indo , tags como onde você esteve .

Uma tag parece um marcador de um ponto importante em particular no passado, como o lançamento de uma versão.

Enquanto uma ramificação é um caminho específico, o projeto está descendo e, portanto, o marcador da ramificação avança com você. Quando terminar, você mescla / exclui o ramo (ou seja, o marcador). Obviamente, nesse ponto, você pode optar por marcar esse commit.

Gazzer
fonte
10

A Git Parable explica como um DVCS típico é criado e por que seus criadores fizeram o que fizeram. Além disso, você pode dar uma olhada no Git for Computer Scientist ; explica o que cada tipo de objeto no Git faz, incluindo ramificações e tags.

Bombe
fonte
6

Uma tag é usada para marcar uma versão, mais especificamente, faz referência a um ponto no tempo em uma ramificação. Uma ramificação é normalmente usada para adicionar recursos a um projeto.

Number45
fonte
4

simples:

As tags sempre apontam para a mesma versão de um projeto, enquanto as cabeças devem avançar à medida que o desenvolvimento avança.

Manual do Usuário Git

Bar Horing
fonte
4

a resposta simples é:

branch: o ponteiro atual do branch move-se a cada confirmação no repositório

mas

tag: a confirmação que uma tag aponta não muda; na verdade, a tag é um instantâneo dessa confirmação.

jsina
fonte