git shallow clone (clone --depth) perde branches remotos

98

Após clonar um repositório remoto, ele não mostra nenhuma ramificação remota pela opção -a. Qual pode ser o problema? Como depurar isso? Neste snippet, dois ramos remotos não são mostrados:

$ git clone --depth 1 git://git.savannah.gnu.org/pythonwebkit.git
$ cd pythonwebkit
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
$ git --version
git version 1.8.3.1

Tentei o mesmo comando em outra máquina, funciona bem:

$ git clone --depth 1 git://git.savannah.gnu.org/pythonwebkit.git
Receiving objects: 100% (186886/186886), 818.91 MiB | 3.44 MiB/s, done.
$ cd pythonwebkit/
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/debian
  remotes/origin/master
  remotes/origin/python_codegen
$ git --version
git version 1.7.1

Também tentei clonar outro repo, funciona bem. Embora eu possa tentar nesta máquina novamente, mas seria melhor saber o que está errado.

Todas as sugestões ou dicas serão mais que bem-vindas.

Edit: Resumo da resposta: desde a versão 1.8.3.2 do git, o "--depth" e "--no-single-branch" precisam ser usados ​​juntos para obter o mesmo comportamento de antes. Isso é considerado uma correção de bug.

minghua
fonte
3
masteré a sua filial local. remotes/origin/masteré a ramificação remota correspondente. Qual é exatamente a pergunta?
michas de
1
Você talvez tenha esquecido a verbosidade? Tentegit branch -avv
jthill
Para michas etc: normalmente não nos referimos ao master como um branch, desculpe a confusão. adicionado "dois ramos remotos não são mostrados". Para jthill: obrigado por lembrar, você está correto.
minghua
1
Obrigado por apresentar git clone --depth=1 --no-single-branch, é disso que preciso na maioria dos casos.
Alireza Mohamadi

Respostas:

63

O comportamento está correto, após a última revisão, o branch master é (uma vez que este é o HEAD do remoto primário) o único branch remoto no repositório:

florianb$ git branch -a
        * master
          remotes/origin/HEAD -> origin/master
          remotes/origin/master

O clone completo oferece novas (todas) ramificações:

florianb$ git branch -a
        * master
          remotes/origin/HEAD -> origin/master
          remotes/origin/debian
          remotes/origin/master
          remotes/origin/python_codegen

Clones rasos

Devido à descrição superficial na documentação técnica, um " git-clone --depth 20 repo[...] resultado [s em] cadeias de commit com um comprimento de no máximo 20." Um clone raso, portanto, deve conter a profundidade solicitada de commits, da ponta de um galho.

As - além - a documentação de git clonepara o --single-branch-option descreve:

"Clone apenas o histórico que leva à ponta de um único ramo, seja especificado pela --branchopção ou o controle remoto do ramo principal HEADaponta. Ao criar um clone raso com a --depthopção, este é o padrão, a menos que --no-single-branchseja fornecido para buscar os históricos próximos ao dicas de todos os ramos. "

Portanto, um clone raso ( com a opção de profundidade ) busca apenas um único ramo (na profundidade solicitada).


Infelizmente, ambas as opções ( --depthe --single-branch) apresentaram falhas no passado e o uso de clones superficiais implica em problemas não resolvidos (como você pode ler no link que postei acima), que é causado pela reescrita de histórico fornecida. Em geral, isso leva a um comportamento um tanto complicado em casos especiais.

Florian Breisch
fonte
1
florianb: qual é a sua versão git? Obrigado por experimentar. Eu fiz o --depth 1 no 1.7.1 agora, ele mostra todos os branches remotos. atualizou a questão com isso. 1 para verificar o problema.
minghua
1
@minghua: Estou usando o 1.8.4 - farei uma pequena investigação se houve um patch para esse problema.
Florian Breisch
1
@minghua: eu editei para refletir as novas descobertas sobre "clones rasos".
Florian Breisch
1
É quase perfeito, exceto apenas uma coisa: o que significa dizer "o proprietário do repo decidiu cortar os outros ramos"? Acho que esses ramos ainda estão lá.
minghua
2
--no-single-branch também clona todas as tags. Podemos evitar isso criando um novo repo, usando a mesma configuração para buscar todos os remotos, ou seja fetch = +refs/heads/*:refs/remotes/origin/*, e executando git fetch --depth 1(sem --tags). Também podemos adicionar tags específicas a serem buscadas, usando como configuração fetch = +refs/tags/v2.0.0:refs/tags/v2.0.0.
Sam Watkins
205

Depois de fazer um clone superficial, para poder verificar outras filiais remotamente ,

  1. Executar (obrigado @jthill):

    git remote set-branches origin '*'
    
  2. Depois disso, faça um git fetch -v

  3. Finalmente git checkout the-branch-i-ve-been-looking-for


A etapa 1 também pode ser feita manualmente por edição .git/config.

Por exemplo, altere a seguinte linha de:

fetch = +refs/heads/master:refs/remotes/origin/master

para (substituir masterpor *):

fetch = +refs/heads/*:refs/remotes/origin/*
marlo
fonte
57
Você também pode usar git remote set-branches origin '*'para todos os ramos, substitua o *por um nome de ramo para um.
jthill
Obrigado! Isso salvou meu dia.
Steven Xu
O que -vvvsignifica em git fetch -vvv? Não encontrei nenhuma informação sobre isso no documento git-fetch
guo
@guo é para o nível de registro verbosityou debugde git. Não é do fetchmétodo.
marlo
1
@ kawing-chiu isso é útil se você tiver tantos branches e o tamanho for muito grande para a 'conexão de internet' anterior e agora você poderia ter todos esses branches. :)
marlo
61

Ao ler as respostas e o comentário de @jthill, o que funcionou melhor para mim foi usar a set-branchesopção no git remotecomando:

$ git clone --depth 1 https://github.com/dogescript/dogescript.git
$ git remote set-branches origin 'remote_branch_name'
$ git fetch --depth 1 origin remote_branch_name
$ git checkout remote_branch_name

Isso muda a lista de branches rastreados pelo remoto nomeado para que possamos buscar e fazer checkout apenas do branch necessário.

alejandrodnm
fonte
15
Pode ser melhor usar de git remote set-branches --add origin 'remote_branch_name'forma que o novo branch seja adicional aos existentes, ao invés de substituí-los na lista remota de branches (ou padrões de branch) para buscar no arquivo .git / config.
dumbledad
2
OMG, a aspa simples 'é importante nogit remote set-branches --add origin 'remote_branch_name'
Fim de semana de
@Weekend não consegui fazer isso funcionar até que deixei as aspas simples de fora
PandaWood
@PandaWood Você provavelmente está no Windows. O sinal "$" na resposta implica Bash (no Unix ou Cygwin / MSYS).
Yongwei Wu
Não vejo nada sobre aspas simples serem necessárias nos documentos e parece funcionar bem sem uma no macOS, pelo menos.
Nickolay