É 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?



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

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á


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.


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>

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.


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


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


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 .


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]

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.)


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?


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


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.

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.