É possível fazer uma verificação esparsa sem verificar primeiro todo o repositório?

171

Estou trabalhando com um repositório com um número muito grande de arquivos que levam horas para serem finalizados. Estou estudando a possibilidade de o Git funcionar bem com esse tipo de repositório agora que ele suporta checkouts esparsos, mas todos os exemplos que posso encontrar fazem o seguinte:

git clone <path>
git config core.sparsecheckout true
echo <dir> > .git/info/sparse-checkout
git read-tree -m -u HEAD

O problema com essa sequência de comandos é que o clone original também faz uma verificação geral. Se você adicionar -n ao comando clone original, o comando read-tree resultará no seguinte erro:

erro: a verificação esparsa não deixa nenhuma entrada no diretório de trabalho

Como fazer a verificação esparsa sem verificar primeiro todos os arquivos?

dromodel
fonte
Nota: git worktree add --no-checkouttambém funcionará (não apenas git clone --no-checkout) com o git 2.9 (apenas 2016). Veja minha resposta abaixo
VonC:
Depois de tentar todas as soluções aqui, a única que apenas baixa o diretório (sem pressionar depois!) É essa .
LondonRob

Respostas:

24

Em 2020, existe uma maneira mais simples de lidar com o check-out esparso sem precisar se preocupar com arquivos .git. Aqui está como eu fiz isso:

git clone <URL> --no-checkout <directory>
cd <directory>
git sparse-checkout init --cone # to fetch only root files
git sparse-checkout set apps/my_app libs/my_lib # etc, to list sub-folders to checkout
# they are checked out immediately after this command, no need to run git pull

Note que requer a versão 2.25 do git instalada. Leia mais sobre isso aqui: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/

ATUALIZAR:

O git clonecomando acima ainda clonará o repositório com seu histórico completo, embora sem fazer o check-out dos arquivos. Se você não precisar do histórico completo, poderá adicionar o parâmetro --thpth ao comando, assim:

# create a shallow clone,
# with only 1 (since depth equals 1) latest commit in history
git clone <URL> --no-checkout <directory> --depth 1
Alexey Grinko
fonte
1
Isso é verdade, bom argumento. Votado. Segui o sparse-checkout --conerecurso em stackoverflow.com/a/59515426/6309
VonC 17/03
Vale a pena adicionar clone parcial ( --filter) à sua resposta aqui.
Tao
@ alexey-grinko, o primeiro comando ainda tinha que clonar todo o repositório em questão, mesmo que não o confirmasse ... eu estava procurando economizar o tempo de não clonar todas as coisas que não preciso .. .
mropp
1
@mropp, atualizei a resposta adicionando um --depthparâmetro que nos permite fazer um clone superficial. Isso vai ajudar? @ Tao, não sei como usar --filterneste caso, eu não tentei. Você poderia dar um exemplo ou postar outra resposta para este tópico?
Alexey Grinko 03/06
4
note que ele não funciona da mesma forma na versão 2.27 - não sei por quê.
Blazes
162

Observe que esta resposta faz o download de uma cópia completa dos dados de um repositório. O git remote add -fcomando clonará todo o repositório. Na página do manual degit-remote :

Com a -fopção, git fetch <name>é executado imediatamente após a configuração das informações remotas.


Tente o seguinte:

mkdir myrepo
cd myrepo
git init
git config core.sparseCheckout true
git remote add -f origin git://...
echo "path/within_repo/to/desired_subdir/*" > .git/info/sparse-checkout
git checkout [branchname] # ex: master

Agora você descobrirá que possui um checkout "podado" apenas com arquivos do caminho / within_repo / para / desejar_subdir presente (e nesse caminho).

Observe que na linha de comando do Windows você não deve citar o caminho, ou seja, você deve alterar o sexto comando com este:

echo path/within_repo/to/desired_subdir/* > .git/info/sparse-checkout

caso contrário, você receberá as aspas no arquivo de verificação esparsa e não funcionará

apenwarr
fonte
3
Não consigo usar o comando "git checkout [branchname]" (também foi encontrado o erro: o Sparse checkout não deixa nenhuma entrada no diretório ativo). Eu usei o "git pull origin master" e funciona corretamente.
Natty3 set13
2
Com a versão 1.7.2.5 do git no linux, obtive os seguintes resultados: echo 'dir / *' verifica apenas os arquivos em dir / mas não em seus subdiretórios; echo 'dir /' (sem asterix!) verifica corretamente a árvore inteira em dir /. HTH
pavek 10/10
37
Isso simplesmente não funcionou para mim - o comando "git remote" resultou no check-out de todo o repositório - bam! - certo então; portanto, o "git config ..." e a especificação de um subdiretório de interesse nos seguintes comandos não tiveram efeito. A URL do repositório especificada no comando "git remote" é apenas o caminho para o arquivo .git de nível superior? Ou deveria ser um caminho para o sub-diretório de interesse?
precisa
10
aqui está uma versão simplificada (não é necessário criar manualmente o diretório, fazer uma adição init e remota, basta fazer o ciclo normal do git clone + checkout com a opção --no-checkout, como mencionado por @onionjake): git clone --no-checkout <project> cd <project> echo <dir>> .git / info / sparse-checkout git checkout <branch>
Gregor
22
O git remote addcomando baixa tudo, porque é o que -ffaz - diz para ele buscar imediatamente, antes de definir as opções de compra esparsa. Mas omitir ou reordenar isso não vai ajudar. As verificações esparsas afetam apenas a árvore de trabalho, não o repositório. Se você deseja que seu repositório faça uma dieta, é necessário examinar as opções --depthou --single-branch.
Miral
43

O clone do Git tem uma opção ( --no-checkoutou -n) que faz o que você deseja.

Na sua lista de comandos, basta alterar:

git clone <path>

Para isso:

git clone --no-checkout <path>

Em seguida, você pode usar a verificação esparsa, conforme indicado na pergunta.

onionjake
fonte
7
sim, ele não faz um checkout, mas ainda faz uma busca para baixar todo o histórico do repo #
Jason S
9
@ Jason, a pergunta era especificamente sobre não fazer um checkout. Se você não quiser, todo o histórico use a --depth <depth>opção git clone. Isso fará o download apenas dos últimos <depth>commits do histórico. Atualmente, não há como baixar parcialmente um único commit com o git, mas se o seu controle remoto o suportar, você poderá usá-lo git archive --remotepara baixar conjuntos parciais de arquivos.
onionjake
Agora você também pode 'verificar' um commit sem baixar nenhum arquivo usando o vfsforgit.org . Isso pode ser útil se alguém estiver tentando fazer check-out apenas de um pequeno subconjunto de uma única confirmação.
onionjake
22

Eu tive um caso de uso semelhante, exceto que eu queria fazer check-out apenas do commit de uma tag e remover os diretórios. O uso --depth 1torna muito escasso e pode realmente acelerar as coisas.

mkdir myrepo
cd myrepo
git init
git config core.sparseCheckout true
git remote add origin <url>  # Note: no -f option
echo "path/within_repo/to/subdir/" > .git/info/sparse-checkout
git fetch --depth 1 origin tag <tagname>
git checkout <tagname>
sourcedelica
fonte
3
- profundidade 1 é chamado de clone superficial, apenas para sua informação.
Mark Allison
1
Isso ajudou! Obrigado
kp123
1
Obrigado por isso. Entendi direito depois de tentar várias outras maneiras de impedir o download de todo o repositório.
J ... S
12

Encontrei a resposta que estava procurando no one-liner publicado anteriormente por pavek (obrigado!). Por isso, queria fornecer uma resposta completa em uma única resposta que funcione no Linux (GIT 1.7.1):

1--> mkdir myrepo
2--> cd myrepo
3--> git init
4--> git config core.sparseCheckout true
5--> echo 'path/to/subdir/' > .git/info/sparse-checkout
6--> git remote add -f origin ssh://...
7--> git pull origin master

Mudei um pouco a ordem dos comandos, mas isso não parece ter nenhum impacto. A chave é a presença da barra final "/" no final do caminho na etapa 5.

JF Bergeron
fonte
3
tem certeza de que é isso que você quer? o -f significa buscar todos os dados, você ainda recebe todas as outras informações que não deseja e é lento. (Isso ainda está "verificando todo o repositório")
Shuman
1
Eu tentei as etapas acima no Windows, mas o checkout de reposição não funciona no prompt de comando, então tentei o shell do Git Bash e funcionou !!. O prompt de comando é capaz de executar todos os comandos do git, como push, pull etc., mas quando se trata de uma verificação esparsa, ele falha.
user593029
Como fazer apenas arquivos do subdiretório. Eu quero buscar apenas os arquivos dentro do subdiretório específico.
Babish Shrestha
@BabishShrestha veja o comentário de onionjake em outra resposta FWIW: |
Rogerdpack 15/09/16
9

Infelizmente, nenhuma das opções acima funcionou para mim, então passei muito tempo tentando diferentes combinações de sparse-checkoutarquivos.

No meu caso, eu queria pular pastas com as configurações do IntelliJ IDEA.

Aqui está o que eu fiz:


Corre git clone https://github.com/myaccount/myrepo.git --no-checkout

Corre git config core.sparsecheckout true

Criado .git\info\sparse-checkoutcom o seguinte conteúdo

!.idea/*
!.idea_modules/*
/*

Execute 'git checkout -' para obter todos os arquivos.


O ponto crítico para fazê-lo funcionar foi adicionar /*o nome da pasta.

Tenho git 1.9

especialista
fonte
3
Não, ele ainda baixa tudo, todos os commits e todos os arquivos, git 2.3.2
Tyguy7
6
As verificações esparsas afetam apenas a árvore de trabalho. Eles não afetam o tamanho do repositório ou o que é buscado. Você precisa de opções diferentes, se quiser.
Miral
Tente Git Bash Shell próxima vez se trabalhar no Windows e uso acima etapas por 'pbetkier' trabalha muito bem
user593029
6

Sim, é possível baixar uma pasta em vez de baixar o repositório inteiro. Mesmo any / last commit

Ótima maneira de fazer isso

D:\Lab>git svn clone https://github.com/Qamar4P/LolAdapter.git/trunk/lol-adapter -r HEAD
  1. -r HEAD baixará apenas a última revisão, ignorará todo o histórico.

  2. Observe o tronco e / pasta específica

Copie e altere o URL antes e depois /trunk/. Espero que isso ajude alguém. Aproveitar :)

Actualizado em 26 de setembro de 2019

Qamar
fonte
aplicável apenas para aqueles provenientes ou usando svn. Não vai votar este.
C Johnson
@ Johnson, como você pode ver, estou clonando a pasta Git Repo. Funcionando bem
Qamar
1
Observe que isso não é algo que o git oferece imediatamente, mas é algo que o hub Git oferece adjacente à oferta regular do Git. No entanto, funciona lindamente quando você pode utilizá-lo. Obrigado!
Qix - MONICA FOI ERRADA EM
1
Das inúmeras sugestões de SO, a sua é a solução mais concisa e clara.
boardrider
5

Resposta atualizada 2020:

Agora existe um comando git sparse-checkoutque apresento em detalhes com o Git 2.25 (primeiro trimestre de 2020)

A resposta de nicono ilustra seu uso:

git sparse-checkout init --cone # to fetch only root files
git sparse-checkout add apps/my_app
git sparse-checkout add libs/my_lib

Ele evoluiu com o Git 2.27 e sabe como "reaplicar" um checkout esparso, como aqui .
Observe que, com o Git 2.28, git statusvocê menciona que você está em um repositório com check-out esparso

Resposta original: 2016

O git 2.9 (junho de 2016) generalizará a --no-checkoutopção para git worktree add(o comando que permite trabalhar com várias árvores de trabalho para um repositório )

Consulte commit ef2a0ac (29 de março de 2016) por Ray Zhang ( OneRaynyDay) .
Ajudado por: Eric Sunshine ( sunshineco) e Junio ​​C Hamano ( gitster) .
(Mesclado por Junio ​​C Hamano - gitster- na confirmação 0d8683c , 13 de abril de 2016)

A git worktreepágina de manual agora inclui:

--[no-]checkout:

Por padrão, o addcheck-out <branch>, no entanto, --no-checkoutpode ser usado para suprimir o check-out, a fim de fazer personalizações, como a configuração de check-outs esparsos .

VonC
fonte
4

Etapas para poupar apenas a pasta específica:

1) git clone --no-checkout  <project clone url>  
2) cd <project folder>
3) git config core.sparsecheckout true   [You must do this]
4) echo "<path you want to sparce>/*" > .git/info/sparse-checkout
    [You must enter /* at the end of the path such that it will take all contents of that folder]
5) git checkout <branch name> [Ex: master]
SANDEEP MACHIRAJU
fonte
Para sua informação, na primeira (1) etapa, você não precisa usar - sem check-out. Apenas clone o repositório inteiro e execute todas as etapas 2 a 5 abaixo (mencionadas acima), você obterá o resultado desejado. Deixe-me saber se você não entendeu.
SANDEEP MACHIRAJU 5/01/19
4

Com base nesta resposta de apenwarr e este comentário de Miral, eu vim com a seguinte solução, que me salvou quase 94% de espaço em disco ao clonar o repositório linux git localmente, enquanto desejava apenas um subdiretório de documentação:

$ cd linux
$ du -sh .git .
2.1G    .git
894M    .
$ du -sh 
2.9G    .
$ mkdir ../linux-sparse-test
$ cd ../linux-sparse-test
$ git init
Initialized empty Git repository in /…/linux-sparse-test/.git/
$ git config core.sparseCheckout true
$ git remote add origin ../linux
# Parameter "origin master" saves a tiny bit if there are other branches
$ git fetch --depth=1 origin master
remote: Enumerating objects: 65839, done.
remote: Counting objects: 100% (65839/65839), done.
remote: Compressing objects: 100% (61140/61140), done.
remote: Total 65839 (delta 6202), reused 22590 (delta 3703)
Receiving objects: 100% (65839/65839), 173.09 MiB | 10.05 MiB/s, done.
Resolving deltas: 100% (6202/6202), done.
From ../linux
 * branch              master     -> FETCH_HEAD
 * [new branch]        master     -> origin/master
$ echo "Documentation/hid/*" > .git/info/sparse-checkout
$ git checkout master
Branch 'master' set up to track remote branch 'master' from 'origin'.
Already on 'master'
$ ls -l
total 4
drwxr-xr-x 3 abe abe 4096 May  3 14:12 Documentation/
$  du -sh .git .
181M    .git
100K    .
$  du -sh
182M    .

Então, diminuí de 2,9 GB para 182 MB, o que já é muito bom.

Embora eu não tenha conseguido fazer isso funcionar git clone --depth 1 --no-checkout --filter=blob:none file:///…/linux linux-sparse-test( sugerido aqui ), os arquivos ausentes foram adicionados como arquivos removidos ao índice. Portanto, se alguém souber o equivalente de git clone --filter=blob:nonefor git fetch, provavelmente podemos economizar mais megabytes. (A leitura da página de manual git-rev-listtambém sugere que há algo parecido --filter=sparse:path=…, mas também não consegui que isso funcionasse.

(Todos tentaram com o git 2.20.1 do Debian Buster.)

Axel Beckert
fonte
1
Feedback interessante. Votado. Eu também não sei --filter=sparse:path=….
VonC
3

Eu sou novo no git, mas parece que se eu fizer o git checkout para cada diretório, ele funcionará. Além disso, o arquivo de verificação esparsa precisa ter uma barra após cada diretório, conforme indicado. Alguém com mais experiência confirma que isso funcionará.

Curiosamente, se você fizer check-out de um diretório que não está no arquivo de check-out esparso, isso parece não fazer diferença. Eles não aparecem no status git e o git read-tree -m -u HEAD não faz com que seja removido. O git reset --hard também não remove o diretório. Alguém mais experiente se preocupa em comentar o que o git pensa em diretórios com check-out, mas que não estão no arquivo de check-out esparso?

dromodel
fonte
1

No git 2.27, parece que o checkout esparso do git evoluiu. A solução nesta resposta não funciona exatamente da mesma maneira (em comparação com o git 2.25)

git clone <URL> --no-checkout <directory>
cd <directory>
git sparse-checkout init --cone # to fetch only root files
git sparse-checkout set apps/my_app libs/my_lib # etc, to list sub-folders to checkout
# they are checked out immediately after this command, no need to run git pull

Esses comandos funcionaram melhor:

git clone --sparse <URL> <directory>
cd <directory>
git sparse-checkout init --cone # to fetch only root files
git sparse-checkout add apps/my_app
git sparse-checkout add libs/my_lib

Veja também: git-clone --sparse e git-sparse-checkout add

nicono
fonte
1
Boa atualização. Votado. Eu editei minha própria resposta de acordo. Apresentei esse comando em dezembro de 2019: stackoverflow.com/a/59515426/6309
VonC
0

No meu caso, quero pular a Podspasta ao clonar o projeto. Eu fiz passo a passo como abaixo e funciona para mim. Espero que ajude.

mkdir my_folder
cd my_folder
git init
git remote add origin -f <URL>
git config core.sparseCheckout true 
echo '!Pods/*\n/*' > .git/info/sparse-checkout
git pull origin master

Lembrete: se você quiser pular mais pastas, basta adicionar mais linha no arquivo de verificação esparsa.

Eric Long
fonte