Como puxar diretório específico com o git


193

Eu tenho um projeto com o git e só quero clonar ou extrair um diretório específico, como myproject / javascript, assim como o subversion.
faça algumas alterações, confirme e empurre novamente.
É possível?


3
verificação esparsa pode interessá-lo (mesmo que você ainda precise buscar tudo): consulte stackoverflow.com/questions/2416815/…
VonC

Respostas:


205
  1. CD na parte superior da sua cópia do repositório
  2. git fetch
  3. git checkout HEAD path/to/your/dir/or/file

    • Onde " path/..." em (3) começa no diretório logo abaixo da raiz do repositório que contém o seu " .../file"

    • Observe que, em vez de "HEAD", o código de hash de uma confirmação específica pode ser usado e, em seguida, você obterá a revisão (arquivo) ou a revisão (dir) específica dessa confirmação.


1
Só percebi que não entendi a pergunta. Em vez disso, minha resposta aborda como fazer check-out de um único arquivo, que pode ser modificado e confirmado.
vergueishon

Você abordou o título da pergunta, que é bom o suficiente. Isso acabou de me salvar. Para mim, essa é a resposta correta - principalmente porque esse foi o principal sucesso do Google para esse problema.
Morgon

21
Isso ainda recebe todo o repo. Para um projeto de 2GB de tamanho, isso não faz economizar muito tempo ..
Pithikos

5
Para aqueles que leem esses comentários e não sabem como isso não responde à pergunta, o que essa solução faz é fornecer uma cópia apenas dessa pasta, mas não é uma cópia de trabalho, o que significa que você não pode modificar e re -commit. Então, como o @Morgon disse, ele aborda o título da pergunta (você PODE puxar apenas um diretório), mas não responde o corpo da pergunta ("faça algumas alterações, confirme e empurre novamente").
msb

@StanHolodnak --não é necessário. Ele força os bits após serem interpretados como um caminho. Portanto, sim, se você tiver um arquivo com o nome --helpque deseja efetuar o checkout, será necessário git checkout HEAD -- --help
prefixá-

105

Em um diretório vazio:

git init
git remote add [REMOTE_NAME] [GIT_URL]
git fetch REMOTE_NAME
git checkout REMOTE_NAME/BRANCH -- path/to/directory

Isso funciona se você só quer usar a versão remota de um arquivo para substituir arquivo local, eu acho
John

isso puxa a pasta também, como não descarregar a pasta, mas apenas coisas dentro da pasta?
Al Kasih

Não há necessidade fetchou checkoutcomando; podemos simplesmente fazer a solicitação pull após o remote addcomando para obter todo o ramo mestre.
Iqra.

2
Como o Pithkos aponta na resposta aceita, essa resposta também fará o download do repositório remoto TODO na sua máquina local. A resposta da shingara é a mais clara - não há como remotamente retirar uma parte de um repositório. No entanto, para aqueles que não se importam com a largura de banda da busca INTEIRA e estão interessados ​​em fazer uma cópia de trabalho de uma parte do cache local, a resposta aceita mostra como. Mas eu só quero deixar claro que todo o histórico do repositório (em um formato compactado) deve ser baixado em sua máquina.
Gabe Halsmer

39

Depois de muito procurar uma resposta, sem encontrar, desistir, tentar de novo e assim por diante, finalmente encontrei uma solução para isso em outro tópico do SO:

Como git-pull, exceto uma pasta

Para copiar e colar o que está lá:

git init
git remote add -f origin <url>
git config core.sparsecheckout true
echo <dir1>/ >> .git/info/sparse-checkout
echo <dir2>/ >> .git/info/sparse-checkout
echo <dir3>/ >> .git/info/sparse-checkout
git pull origin master

Para fazer o que o OP deseja (trabalhe em apenas um diretório), basta adicionar esse diretório ao .git/info/sparse-checkoutexecutar as etapas acima.

Muito obrigado a @cforbish!


2
Estou postando aqui principalmente porque sempre que tento pesquisar no Google como fazer isso, esse é um resultado excelente, e esse segmento nem chega perto de ser exibido. :( Eu me sinto mal copiar-colar, mas eu acho que é SO melhores práticas?
MSB

1
Esta é a única solução limpa. Tentei as respostas acima. Depois de verificar minha ramificação com as outras respostas, não consegui extrair e tive vários novos arquivos que precisavam ser confirmados. Com esta solução, tudo parece certo. Mas NOTA: Independentemente do ramo que foi retirado, git vai pensar que você está em master. Apenas certifique-se que você faz git branch --set-upstream-to=origin/<branch>para puxar corretamente
seebiscuit

12

Não é possível. Você precisa puxar todo o repositório ou nada.


1
Mesmo que você precise buscar tudo, seria interessante um puxão em uma árvore de trabalho de caixa esparsa? Veja stackoverflow.com/questions/2416815/…
VonC

10
Só para adicionar isso, a razão pela qual você não pode extrair apenas um diretório é porque o git usa o rastreamento semântico de dados, não o rastreamento semântico de arquivos, para que você possa mover o código (ou outros dados) para dentro e para fora dos arquivos sem precisar informar a fonte sistema de rastreamento (até que você atualize, é claro.) Por causa disso, o código também pode entrar e sair dos diretórios sem problemas, portanto, pegar apenas um diretório não faz tanto sentido. Espero que isto ajude.
OmnipotentEntity

12
@OmnipotentEntity Desculpe, mas IMHO faz sentido. A implementação não deve limitar o uso. O Git sabe o que são diretórios (pelo menos ao criar uma cópia de trabalho local), portanto não há razão para que ele não possa executar alguma operação semelhante no servidor e apenas enviar a saída relevante. Concedido, isso não está implementado atualmente, mas isso se deve à falta de um recurso, não a uma impossibilidade fundamental. Pessoalmente, acho que é um recurso muito importante, mas ei, essa é uma das razões pelas quais evito o git quando possível.
Basic

10

Talvez este comando possa ser útil:

git archive --remote=MyRemoteGitRepo --format=tar BranchName_or_commit  path/to/your/dir/or/file > files.tar

"Et voilà"


2
Isso faz o download de um diretório específico de arquivo para fins de arquivamento; isso não extrai uma cópia que você pode modificar e empurrar para trás.
LeetNightshade

Muito legal. Provavelmente, não é aceitável como solução para o OP, mas na verdade era o que eu procurava, pois só preciso pesquisar o conteúdo de uma pasta grande em um repositório ainda maior que definitivamente não quero buscar e não preciso modificar / empurrar.
Oliver

7

Se você deseja obter as alterações mais recentes em um diretório sem inseri-lo, é possível:

$ git -C <Path to directory> pull


1

Tentei e testei isso funciona!

mkdir <directory name> ;  //Same directory name as the one you want to pull
cd <directory name>;
git remote add origin <GIT_URL>;
git checkout -b '<branch name>';
git config core.sparsecheckout true;
echo <directory name>/ >> .git/info/sparse-checkout;
git pull origin <pull branch name>

Espero que isso tenha sido útil!


0

Às vezes, você só quer dar uma olhada nas cópias anteriores dos arquivos sem a dificuldade de passar pelas diferenças.

Nesse caso, é igualmente fácil criar um clone de um repositório e verificar o commit específico no qual você está interessado e dar uma olhada no subdiretório nesse repositório clonado. Como tudo é local, você pode excluir este clone quando terminar.


-1

Por toda essa luta com caminhos de arquivos teóricos e exemplos como eu, aqui está um exemplo do mundo real: a Microsoft oferece seus documentos e exemplos no git hub, infelizmente eles reúnem todos os seus arquivos de exemplo para uma grande quantidade de tópicos neste repositório:

https://github.com/microsoftarchive/msdn-code-gallery-community-s-z

Eu só estava interessado nos arquivos js do Microsoft Dynamics no caminho

msdn-code-gallery-community-s-z/Sdk.Soap.js/

então eu fiz o seguinte

Crie um

msdn-code-gallery-community-s-zSdkSoapjs\.git\info\sparse-checkout

arquivo na minha pasta de repositórios no disco

git sparse-checkout init

nesse diretório usando o cmd no windows

O conteúdo do arquivo

msdn-code-gallery-community-s-zSdkSoapjs\.git\info\sparse-checkout

é

Sdk.Soap.js/*

finalmente faça um

git pull origin master
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.