O que é a tag git, como criar tags e como fazer check-out das tags remotas git

524

quando eu fizer o check-out remoto tag git use comando como este:

git checkout -b local_branch_name origin/remote_tag_name

Eu recebi um erro como este:

error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.

Posso encontrar remote_tag_name quando uso o comando git tag.

Ryanqy
fonte

Respostas:

1154

Vamos começar explicando o que é uma tag no git

insira a descrição da imagem aqui

Uma tag é usada para rotular e marcar um commit específico no histórico.
Geralmente é usado para marcar pontos de liberação (por exemplo, v1.0, etc.).

Embora uma tag possa parecer semelhante a uma ramificação , ela não é alterada . Aponta diretamente para um commit específico na história.

insira a descrição da imagem aqui


Você não poderá fazer check-out das tags se elas não estiverem localmente no seu repositório; portanto, primeiro você deve fazer fetchas tags no seu repositório local.

Primeiro, verifique se a tag existe localmente fazendo

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

Em seguida, verifique a tag executando

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

Em vez de originusar o tags/prefixo.


Neste exemplo, você tem 2 tags versão 1.0 e versão 1.1. Você pode vê-las com uma das seguintes opções:

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

Todas as opções acima farão o mesmo, pois a tag é apenas um ponteiro para um determinado commit.

insira a descrição da imagem aqui
origem: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png


Como ver a lista de todas as tags?

# list all tags
$ git tag

# list all tags with given pattern ex: v-
$ git tag --list 'v-*'

Como criar tags?

Existem 2 maneiras de criar uma tag:

# lightweight tag 
$ git tag 

# annotated tag
$ git tag -a

A diferença entre os dois é que, ao criar uma tag anotada, você pode adicionar metadados conforme o seu git commit:
nome, email, data, comentário e assinatura

insira a descrição da imagem aqui

Como excluir tags?

# delete any (local) given tag
$ git tag -d <tag name>

# Delete a tag from the server with push tags
$ git push --delete origin <tag name>

Como clonar uma tag específica?

Para capturar o conteúdo de uma determinada tag, você pode usar o checkoutcomando Conforme explicado acima, as tags são como qualquer outro commit, portanto, podemos usar checkoute, em vez de usar o SHA-1, basta substituí-lo pelo tag_name

Opção 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>

Opção 2:

Usando o comando clone

Como o git suporta clone superficial adicionando o --branchcomando clone, podemos usar o nome da tag em vez do nome da ramificação. O Git sabe como "traduzir" o SHA-1 fornecido para o commit relevante

# Clone a specific tag name using git clone 
$ git clone <url> --branch=<tag_name>

git clone --branch =

--branch também pode pegar tags e desanexar o HEAD naquele commit no repositório resultante.


Como enviar tags?

git push --tags

Para enviar todas as tags por push:

# Push all tags
$ git push --tags 

Usando o em refs/tagsvez de apenas especificar o <tagname>.

Por quê? - É recomendado o uso, refs/tagspois às vezes as tags podem ter o mesmo nome que seus branches e o simples git push pressiona o branch em vez da tag

Para enviar tags anotadas e cadeia de histórico atual, use:

git push --follow-tags

Esse sinalizador --follow-tagsenvia as confirmações e somente as tags que são ambas:

  • Tags anotadas (para que você possa pular tags de criação local / temporária)
  • Tags acessíveis (um ancestral) da ramificação atual (localizada no histórico)

insira a descrição da imagem aqui

No Git 2.4, você pode configurá-lo usando a configuração

$ git config --global push.followTags true

Folha de dicas: insira a descrição da imagem aqui


CodeWizard
fonte
3
agradável. git checkout A. o que é A? Como você criou A?
Honey
3
@CodeWizard Bom fluxograma! Qual software você usou para produzi-lo?
Giovanni Lovato
4
@Honey Aé um hash comprometer
Alex Baklanov
2
@GiovanniLovato O fluxograma é de terceiros. O link para a imagem é backlog.com/git-tutorial/img/post/stepup/…, que é desta página backlog.com/git-tutorial/stepup/stepup4_1.html do site chamado Git Beginner's Guide for Dummies (backlog .com).
George
2
Vale a pena notar que git checkout tags/<tag_name> -b <branch_name>requer o -b <branch_name>. git checkout tags/<tag_name>me deu uma cabeça desapegada. De acordo com este artigo sobre cabeça desanexada , você evita uma cabeça desanexada criando e excluindo temporariamente uma ramificação. Este é um fluxo de trabalho bastante estranho. Claramente, eu, como usuário do git, preciso me acostumar a criar e excluir ramos por diversão e lucro.
Icc97 29/08/19
194

(Essa resposta demorou um pouco para ser escrita, e a resposta do codeWizard está correta em objetivo e essência, mas não totalmente completa, portanto, postarei isso de qualquer maneira.)


Não existe uma "tag Git remota". Existem apenas "tags". Eu aponto tudo isso para não ser pedante, 1 mas porque há muita confusão sobre isso com usuários casuais do Git, e a documentação do Git não ajuda muito 2 para iniciantes. (Não está claro se a confusão ocorre por causa da documentação inadequada ou se a documentação ruim ocorre porque isso é inerentemente um tanto confuso, ou o quê.)

Não são "filiais remotas", mais propriamente chamados "-monitoramento remoto ramos", mas é importante notar que estas são realmente entidades locais. Porém, não há tags remotas (a menos que você as (re) invente). Existem apenas tags locais, então você precisa obtê-la localmente para usá-lo.

A forma geral de nomes para confirmações específicas - às quais o Git chama referências - é qualquer sequência iniciada refs/. Uma sequência que começa com refs/heads/nomes de uma ramificação; uma sequência começando com refs/remotes/nomes de uma ramificação de rastreamento remoto; e uma sequência iniciando com refs/tags/nomes de uma tag. O nome refs/stashé a referência de stash (conforme usado por git stash; observe a falta de uma barra final).

Existem alguns nomes incomuns casos especiais que não começam com refs/: HEAD, ORIG_HEAD, MERGE_HEAD, e CHERRY_PICK_HEAD, em particular, são também nomes que podem se referem a commits específicas (embora HEADnormalmente contém o nome de uma sucursal, ou seja, contém ). Mas, em geral, as referências começam com .ref: refs/heads/branchrefs/

Uma coisa que o Git faz para tornar isso confuso é que ele permite que você omita refs/a palavra, e geralmente a palavra seguinte refs/. Por exemplo, você pode omitir refs/heads/ou refs/tags/ao se referir a uma filial ou tag local - e, de fato, deve omitir refs/heads/ao fazer check-out de uma filial local! Você pode fazer isso sempre que o resultado for inequívoco, ou - como acabamos de observar - quando precisar fazê-lo (por ).git checkout branch

É verdade que as referências existem não apenas no seu próprio repositório, mas também em repositórios remotos. No entanto, o Git fornece acesso às referências de um repositório remoto apenas em horários muito específicos: ou seja, durante fetche pushoperações. Você também pode usar git ls-remoteou git remote showvê-los, mas fetche pushsão os pontos de contato mais interessantes.

Refspecs

Durante fetche push, o Git usa strings que chama refspecs para transferir referências entre o repositório local e remoto. Portanto, é nesses momentos, e via refspecs, que dois repositórios Git podem entrar em sincronia. Depois que seus nomes estiverem sincronizados, você poderá usar o mesmo nome que alguém com o controle remoto usa. Há alguma mágica especial aqui fetch, porém, e afeta os nomes das filiais e os tags.

Você deve pensar git fetchem direcionar o seu Git para chamar (ou talvez mensagem de texto) outro Git - o "remoto" - e conversar com ele. No início desta conversa, o controle remoto lista todas as suas referências: tudo dentro refs/heads/e tudo dentro refs/tags/, juntamente com outras referências que ele possui. Seu Git varre esses e (com base na busca usual refspec) renomeia suas ramificações.

Vamos dar uma olhada no refspec normal para o controle remoto chamado origin:

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

Este refspec instrui o Git a usar todos os nomes correspondentes - refs/heads/*ou seja, todas as ramificações do controle remoto - e alterar seu nome para refs/remotes/origin/*, ou seja, manter a parte correspondente igual, alterando o nome da ramificação ( refs/heads/) para um nome de ramificação de rastreamento remoto ( refs/remotes/especificamente , refs/remotes/origin/).

É através deste refspec que originas ramificações se tornam suas ramificações de rastreamento remoto para controle remoto origin. O nome da filial se torna o nome da filial de rastreamento remoto, com o nome do controle remoto, nesse caso origin, incluído. O sinal de mais +na frente do refspec define o sinalizador "force", ou seja, sua ramificação de rastreamento remoto será atualizada para corresponder ao nome da ramificação do controle remoto, independentemente do que for necessário para fazer a correspondência. (Sem isso +, as atualizações de ramificação são limitadas a alterações de "avanço rápido" e as atualizações de tags são simplesmente ignoradas desde a versão 1.8.2 do Git, aproximadamente - antes disso, as mesmas regras de avanço rápido são aplicadas.

Tag

Mas e as tags? Não há refspec para eles - pelo menos, não por padrão. Você pode definir um, caso em que a forma do refspec depende de você; ou você pode correr git fetch --tags. O uso --tagstem o efeito de adicionar refs/tags/*:refs/tags/*ao refspec, ou seja, ele traz todas as tags ( mas não atualiza sua tag se você já tiver uma tag com esse nome, independentemente do que a tag do controle remoto diz Edit, jan 2017: a partir do Git 2.10 , testing mostra que --tagsatualiza forçosamente suas tags a partir das tags do controle remoto, como se o refspec lesse +refs/tags/*:refs/tags/*; isso pode ser uma diferença no comportamento de uma versão anterior do Git).

Observe que não há renomeação aqui: se remote origintiver tag xyzzy, e você não tiver, e você git fetch origin "refs/tags/*:refs/tags/*", você será refs/tags/xyzzyadicionado ao seu repositório (apontando para o mesmo commit que no remoto). Se você usar +refs/tags/*:refs/tags/*, sua tag xyzzy, se você tiver uma, será substituída pela de origin. Ou seja, o +sinalizador de força em um refspec significa "substituir o valor da minha referência pelo valor que meu Git obtém do Git".

Tags automagic durante a busca

Por motivos históricos, 3 se você não usar nem a --tagsopção nem a --no-tagsopção, git fetchexecutará uma ação especial. Lembre-se de que dissemos acima que o controle remoto exibe todas as referências ao Git local, independentemente de o Git local querer vê-las ou não. 4 Seu Git toma nota de todas as tags que vê neste momento. Então, quando começar a baixar qualquer objeto de confirmação necessário para lidar com o que estiver buscando, se um deles confirmar o mesmo ID de qualquer uma dessas tags, o git adicionará essa tag - ou essas tags, se várias tags tiverem esse ID - a seu repositório.

Editar, Jan 2017: Teste mostra que o comportamento em Git 2.10 agora é: Se o seu Git fornece uma tag chamado T , e você não tem uma etiqueta com o nome T , e a cometer ID associada a T é um ancestral de um dos seus ramos que você git fetchestá examinando, seu Git adiciona T às suas tags com ou sem --tags. Adicionar --tagsfaz com que o Git obtenha todas as suas tags e também force a atualização.

Bottom line

Você pode ter que usar git fetch --tagspara obter as tags. Se os nomes de suas marcas entrarem em conflito com os nomes de marcas existentes, você pode (dependendo da versão do Git) precisar excluir (ou renomear) algumas git fetch --tagsdelas e depois executá -las para obtê-las. Como as tags - diferentemente das ramificações remotas - não têm renomeação automática, os nomes das tags devem corresponder aos nomes das tags, e é por isso que você pode ter problemas com conflitos.

Na maioria dos casos normais, no entanto, um simples git fetchfará o trabalho, trazendo suas confirmações e suas tags correspondentes, e como elas - quem quer que sejam - marcarão as confirmações no momento em que publicarem essas confirmações, você as acompanhará. Se você não criar suas próprias tags, nem misturar seu repositório e outros repositórios (por meio de vários controles remotos), também não terá colisões de nomes de tags, portanto não precisará se preocupar em excluir ou renomear tags para obtenha suas tags.

Quando você precisar de nomes qualificados

Mencionei acima que você pode omitir refs/quase sempre, e refs/heads/e refs/tags/e assim por diante na maioria das vezes. Mas quando você não pode ?

A (de qualquer maneira ou quase completa) resposta completa é a gitrevisionsdocumentação . O Git resolverá um nome para um ID de confirmação usando a sequência de seis etapas fornecida no link. Curiosamente, as tags substituem as ramificações: se houver uma tag xyzzye uma ramificação xyzzy, e elas apontarem para confirmações diferentes, então:

git rev-parse xyzzy

fornecerá o ID para o qual a tag aponta. No entanto - e é isso que está faltando gitrevisions- git checkoutprefere os nomes das ramificações, git checkout xyzzyo colocará na ramificação, desconsiderando a tag.

Em caso de ambiguidade, você quase sempre pode soletrar o nome ref usando seu nome completo, refs/heads/xyzzyou refs/tags/xyzzy. (Note que este faz o trabalho com git checkout, mas de uma forma talvez inesperada: git checkout refs/heads/xyzzyprovoca um checkout-HEAD destacada em vez de um check-out ramo É por isso que você só tem que nota isso. git checkoutUsará o nome curto como um nome de filial em primeiro lugar: é assim que você verifique a ramificação xyzzymesmo que a tag xyzzyexista. Se você quiser fazer check-out da tag, poderá usá-la refs/tags/xyzzy.)

Como o gitrevisionsGit tentará (como notas) , você também pode simplesmente escrever para identificar o commit marcado . (Se alguém conseguiu escrever uma referência válida nomeada em , no entanto, isso será resolvido como . Mas normalmente apenas os vários nomes devem estar .)refs/nametags/xyzzyxyzzyxyzzy$GIT_DIR$GIT_DIR/xyzzy*HEAD$GIT_DIR


1 Ok, ok, "não apenas para ser pedante". :-)

2 Alguns diriam "muito inútil", e eu tenderia a concordar, na verdade.

3 Basicamente, git fetche todo o conceito de controles remotos e refspecs, foi um acréscimo tardio ao Git, ocorrendo na época do Git 1.5. Antes disso, havia apenas alguns casos especiais ad-hoc, e a busca de tags era um deles, por isso foi adquirido por meio de um código especial.

4 Se ajudar, pense no Git remoto como um pisca - pisca , no significado da gíria.

torek
fonte
Ótima redação. Um pequeno detalhe: git fetchbuscará apenas as tags do controle remoto, dado o --tagsargumento.
Cweekly
@cweekly: o comportamento de --tags, --no-tagse o padrão é realmente muito complicado. O padrão é trazer as tags que você não possui e que estão nos commits que você está trazendo. (Veja a edição de janeiro de 2017). Mas também existem falhas aqui, e o Git moderno está com suas - tags / --no-tags manipulação de código revisado mais uma vez, o que provavelmente levará a casos de canto ainda mais especiais.
Torek 26/10/19
1

Para fazer o checkout de uma tag git, você deve executar o seguinte comando

git checkout tags/tag-name -b branch-name

por exemplo, conforme mencionado abaixo.

 git checkout tags/v1.0 -b v1.0-branch

Para buscar todas as tags, use o comando

git fetch --all --tags
mani
fonte
0

Para obter o código de tag específico, tente criar uma nova ramificação, adicione o código de tag nele. Eu fiz isso por comando:$git checkout -b newBranchName tagName

Rahul Khatri
fonte