"Git fetch --tags" inclui "git fetch"?

270

Uma pergunta simples e agradável - a função de "git fetch" é um subconjunto estrito de git fetch --tags?

Ou seja, se eu correr git fetch --tags, existe alguma razão para correr imediatamente git fetchlogo depois?

Que tal git pulle git pull --tags? Mesma situação?

davidA
fonte
11
Iniciando o Git 1..9 / 2.0 (primeiro trimestre de 2014), a resposta será sim . Veja minha resposta abaixo
VonC
3
Para o editor que "corrigiu meu texto" com uma edição - não é necessariamente necessário colocar um hífen ou uma sigla em maiúscula; portanto, sua edição estava gramaticalmente incorreta, e foi por isso que a rejeitei.
DavidA 17/0518

Respostas:

176

Nota: a partir do git 1.9 / 2.0 (primeiro trimestre de 2014) , git fetch --tagsbusca tags além daquelas que são buscadas pela mesma linha de comando sem a opção

Veja commit c5a84e9 de Michael Haggerty (mhagger) :

Anteriormente, a --tagsopção " " da busca era considerada equivalente à especificação do refspec

refs/tags/*:refs/tags/*

na linha de comando; em particular, fez com que a remote.<name>.refspecconfiguração fosse ignorada.

Mas não é muito útil buscar tags sem também buscar outras referências, ao passo que é bastante útil poder buscar tags além de outras referências.
Portanto, altere a semântica desta opção para fazer a última.

Se um usuário deseja buscar apenas tags, ainda é possível especificar um refspec explícito:

git fetch <remote> 'refs/tags/*:refs/tags/*'

Observe que a documentação anterior à 1.8.0.3 era ambígua sobre esse aspecto " fetch --tags" do comportamento.
A confirmação f0cb2f1 ( 14-12-2012 ) fetch --tagsfez com que a documentação correspondesse ao comportamento antigo.
Essa confirmação altera a documentação para corresponder ao novo comportamento (consulteDocumentation/fetch-options.txt ).

Solicite que todas as tags sejam buscadas no controle remoto , além do que estiver sendo buscado .


Como o Git 2.5 (segundo trimestre de 2015) git pull --tagsé mais robusto:

Ver commit 19d122b por Paul Tan ( pyokagan) , 13 de maio de 2015.
(Mesclado por Junio ​​C Hamano - gitster- no commit cc77b99 , 22 de maio de 2015)

pull: remover --tags erro no caso de candidatos sem mesclagem

Como o 441ed41 (" git pull --tags": erro com uma mensagem melhor., 28-12-2007, Git 1.5.4+), git pull --tagsimprimiria uma mensagem de erro diferente se git-fetchnão retornasse nenhum candidato de mesclagem:

It doesn't make sense to pull all tags; you probably meant:
       git fetch --tags

Isso ocorre porque, naquele momento, git-fetch --tagssubstituiria quaisquer refspecs configurados e, portanto, não haveria candidatos à mesclagem. A mensagem de erro foi introduzida para evitar confusão.

No entanto, como c5a84e9 ( fetch --tags: buscar tags além de outras coisas, 2013-10-30, Git 1.9.0+), buscaria git fetch --tagstags além de quaisquer refspecs configurados.
Portanto, se ocorrer qualquer situação de candidatos não mesclados, não é porque --tagsfoi definido. Como tal, esta mensagem de erro especial agora é irrelevante.

Para evitar confusão, remova essa mensagem de erro.


Com o Git 2.11+ (quarto trimestre de 2016) git fetché mais rápido.

Veja commit 5827a03 (13 de outubro de 2016) por Jeff King ( peff) .
(Mesclado por Junio ​​C Hamano - gitster- na confirmação 9fcd144 , 26 de outubro de 2016)

fetch: use "quick" has_sha1_filepara seguir as tags

Ao buscar em um controle remoto que possui muitas tags que são irrelevantes para as ramificações que seguimos, perdemos muitos ciclos ao verificar se o objeto apontado por uma tag (que não vamos buscar!) Existe em nosso repositório com muito cuidado.

Este patch ensina a buscar o uso do HAS_SHA1_QUICK para sacrificar a precisão pela velocidade, nos casos em que podemos ser atrevidos com uma reembalagem simultânea.

Aqui estão os resultados do script perf incluído, que configura uma situação semelhante à descrita acima:

Test            HEAD^               HEAD
----------------------------------------------------------
5550.4: fetch   11.21(10.42+0.78)   0.08(0.04+0.02) -99.3%

Isso se aplica apenas a uma situação em que:

  1. Você tem muitos pacotes no lado do cliente para ficar reprepare_packed_git()caros (a parte mais cara é encontrar duplicatas em uma lista não classificada, que atualmente é quadrática).
  2. Você precisa de um grande número de referências de tags no lado do servidor candidatas ao acompanhamento automático (ou seja, que o cliente não possui). Cada um deles dispara uma releitura do diretório do pacote.
  3. Em circunstâncias normais, o cliente seguiria automaticamente essas tags e, após uma grande busca, (2) não seria mais verdadeiro.
    Mas se essas tags apontarem para um histórico desconectado do que o cliente busca, ele nunca seguirá automaticamente, e esses candidatos terão um impacto sobre cada busca.

O Git 2.21 (fevereiro de 2019) parece ter introduzido uma regressão quando a configuração nãoremote.origin.fetch é a padrão ( '+refs/heads/*:refs/remotes/origin/*')

fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed

O Git 2.24 (quarto trimestre de 2019) adiciona outra otimização.

Veja commit b7e2d8b (15 set 2019) de Masaya Suzuki ( draftcode) .
(Incorporado por Junio ​​C Hamano - gitster- in commit 1d8b0df , 07 out 2019)

fetch: use oidsetpara manter os OIDs desejados para uma pesquisa mais rápida

Durante git fetch, o cliente verifica se os OIDs das tags anunciadas já estão no conjunto de OIDs da solicitação de busca.
Essa verificação é feita em uma varredura linear.
Para um repositório com muitas referências, a repetição dessa verificação leva mais de 15 minutos.

Para acelerar isso, crie um oid_setpara OIDs de outros árbitros.

VonC
fonte
Este tópico na git-list discute a possibilidade de alterar o comportamento das git fetch <remote> <branch>tags de acompanhamento automático (uma vez que já atualiza os rastreamentos remotos CONTRA intenções originais): public-inbox.org/git/…
ankostis
@ankostis Interessante: como Junio ​​menciona em public-inbox.org/git/… , "voltar ao comportamento antigo pode ser uma opção para resolver o problema que está sendo discutido neste tópico". (mas eles não vão: public-inbox.org/git/… )
VonC
Teria sido possível para o Git expor uma complexidade mais desnecessária ao usuário final, exigindo comandos pesados ​​de sintaxe a ponto de parecerem com hacks para executar operações comuns? Eu não acho que o suficiente dos internos seja necessário ainda.
John Fantastico
1
@JohnFantastico Entendo esse ponto de vista. Já vi isso antes: news.ycombinator.com/item?id=16587496 . Ou hackernoon.com/… ("Os comandos Git são apenas uma abstração com vazamento sobre o armazenamento de dados.")
VonC
1
@Vadorequest Obrigado. Atualizei a resposta e vou dar uma olhada na lista de discussão: public-inbox.org/git/?q=fetch
VonC
131

Nota: esta resposta é válida apenas para o git v1.8 e anterior.

Muito disso foi dito nas outras respostas e comentários, mas aqui está uma explicação concisa:

  • git fetchbusca todas as cabeças de ramificação (ou todas especificadas pela opção de configuração remote.fetch), todas as confirmações necessárias para elas e todas as tags que são acessíveis a partir dessas ramificações. Na maioria dos casos, todas as tags são acessíveis dessa maneira.
  • git fetch --tagsbusca todas as tags, todas as confirmações necessárias para elas. Ele não atualizará os cabeçalhos das ramificações, mesmo que sejam acessíveis a partir das tags que foram buscadas.

Resumo: se você realmente deseja estar totalmente atualizado, usando apenas a busca, você deve fazer as duas coisas.

Também não é "duas vezes mais lento", a menos que você queira digitar na linha de comando; nesse caso, os aliases resolvem o seu problema. Essencialmente, não há custos adicionais ao fazer os dois pedidos, pois eles estão solicitando informações diferentes.

Cascabel
fonte
2
Obrigado por seu comentário. Estou executando o git no Cygwin em uma rede de alta latência - é duas vezes mais lenta quando não há nada para buscar por (cerca de 5 segundos).
DavidA 30/07/2009
Uau. O git-remote funciona melhor? Olhando brevemente a fonte, acho que ela pode fazer apenas uma única ligação - mas não tenho muita certeza se ela pegará as tags que não estão no ramo. Honestamente, eu não sei se eu já vi alguma tag que não esteja em um galho. Com as coisas que retiro, a única maneira de acontecer se eu esperasse tanto tempo que perdesse um release de manutenção, um release de recurso e a descontinuação da manutenção do release antigo.
Cascabel
Penso que o problema é que 'git fetch' apenas busca tags nos ramos rastreados . Temos um script que permite que os usuários selecionem uma ramificação em funcionamento; portanto, por padrão, existem muitas ramificações que atualmente não são rastreadas por um indivíduo.
DavidA
Eu não tentei git-remote ainda, mas é na minha crescente lista de coisas a fazer :)
Davida
7
Observe que git remote updatenão é realmente um substituto para git fetche git fetch --tags. git remote updatenão atualizará as tags existentes que foram alteradas, embora traga novas tags. Somente git fetch --tagsatualizará as tags já existentes.
Larsks
48

Eu mesmo vou responder isso.

Eu determinei que há uma diferença. "git fetch --tags" pode trazer todas as tags, mas não traz nenhum novo commit!

Acontece que é preciso fazer isso para estar totalmente "atualizado", ou seja, replicado um "git pull" sem a mesclagem:

$ git fetch --tags
$ git fetch

É uma pena, porque é duas vezes mais lento. Se apenas o "git fetch" tivesse a opção de fazer o que normalmente faz e trazer todas as tags.

davidA
fonte
Interessante, eu não experimentei isso (provavelmente porque meu repositório estava atualizado no momento do meu teste.) +1
VonC
1
Que tal um ' git remote update myRemoteRepo': isso buscaria conteúdo e tags remotos ?
VonC 30/07/2009
1
eu faço git fetch isso o tempo todo e, consistentemente, retira todos os novos commit e novas tags. Qual versão do Git você está executando?
Tim Visher
4
FTR, 'git remote update myRemoteRepo' não funciona bem - não parece fazer o que 'git fetch && git fetch --tags' faz, especialmente porque uma mesclagem subsequente não tem efeito.
davidA 3/08/09
1
O @TimVisher git fetchnão pega tags que não estão no log de confirmação de uma ramificação. A interface do usuário do jQuery faz isso, por exemplo, em uma tag de lançamento. Fazemos git checkout -b temp-branch, fazemos nosso lançamento, adicionamos os arquivos necessários para o lançamento, atualizamos a versão etc., e git commit -m "1.10.x" ; git tag 1.10.x; git push --tagsdepois excluímos nosso ramo temporário local. Não há ramificação remota que atinja essa tag e git fetchnunca fará o download.
Gnarf
31

O problema geral aqui é que git fetchserá buscado +refs/heads/*:refs/remotes/$remote/*. Se algum desses commits tiver tags, essas tags também serão buscadas. No entanto, se houver tags inacessíveis por qualquer filial no controle remoto, elas não serão buscadas.

A --tagsopção muda o refspec para +refs/tags/*:refs/tags/*. Você pode pedir git fetchpara pegar os dois. Tenho certeza de que, basta fazer um, git fetch && git fetch -tvocê usaria o seguinte comando:

git fetch origin "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"

E se você quiser tornar isso o padrão para este repositório, poderá adicionar um segundo refspec à busca padrão:

git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"

Isso adicionará uma segunda fetch =linha na .git/configpara este controle remoto.


Passei um tempo procurando a maneira de lidar com isso em um projeto. Isto é o que eu vim com.

git fetch -fup origin "+refs/*:refs/*"

No meu caso, eu queria esses recursos

  • Pegue todas as cabeças e tags do controle remoto, então use refspec refs/*:refs/*
  • Substituir ramificações e tags locais com avanço rápido +antes do refspec
  • Substituir ramificação com check-out atualmente, se necessário -u
  • Excluir ramificações e tags não presentes no controle remoto -p
  • E forçar a ter certeza -f
gnarf
fonte
Essa deve ser a resposta.
redolent
+1 para "A --tagsopção alterna o refspec para +refs/tags/*:refs/tags/*". Embora man git-fetch,, parece especificar esse refspec sem o líder +( refs/tags/*:refs/tags/*).
Dmitry Minkovsky
remote.origin.fetcho padrão +refs/heads/*:refs/remotes/origin/*é, ou seja, a +versão, não é? (O que significa, origem / ramo será substituído, não importa onde origem / filial é agora localmente.)
Robert Siemer
... e no momento da redação deste artigo, as recentes git --tagsbuscavam tags , além de todo o resto. Veja a resposta de @VonC.
Robert Siemer
10

Na maioria das situações, git fetch deve fazer o que deseja, que é 'obter algo novo do repositório remoto e colocá-lo na sua cópia local sem mesclar-se às suas filiais locais'. git fetch --tagsfaz exatamente isso, exceto que ele não recebe nada, exceto novas tags.

Nesse sentido, não git fetch --tagsé de forma alguma um superconjunto degit fetch . Na verdade, é exatamente o oposto.

git pull, é claro, não passa de um invólucro para a git fetch <thisrefspec>; git merge. É recomendável que você se acostume a fazer a git fetching manual e git mergeing antes de saltar paragit pull simplesmente porque ajuda a entender o que git pullestá fazendo em primeiro lugar.

Dito isto, o relacionamento é exatamente o mesmo que com git fetch. git pullé o superconjunto de git pull --tags.

Tim Visher
fonte
1
"git pull é o superconjunto de git pull - tags" - mas ... 'git fetch' não é o superconjunto de 'git fetch - tags', então o relacionamento não é exatamente o mesmo ...?
DavidA
9
Só encontrei esta pergunta ... bem, parece-me que git pullse não obter todas as marcas, mas apenas aqueles acessível a partir das cabeças de filiais atuais. No entanto, git pull --tagsbusca todas as tags e é aparentemente equivalente a git fetch --tags.
Archimedix
2
git fetch upstream --tags

funciona muito bem, ele receberá apenas novas tags e não receberá nenhuma outra base de código.

PAnand
fonte
1
upstreamé normalmente chamado origin. Eu acho que upstreamé um nome usado pelo GitHub. De qualquer forma, o nome a ser usado é o mostrado por git remote.
Fabio diz Reinstate Monica