È possibile effettuare un checkout sparso senza prima controllare l'intero repository?


171

Sto lavorando con un repository con un numero molto elevato di file che richiede ore per il checkout. Sto esaminando la possibilità che Git funzioni bene con questo tipo di repository ora che supporta checkout sparsi, ma ogni esempio che trovo fa quanto segue:

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

Il problema con questa sequenza di comandi è che anche il clone originale fa un checkout. Se si aggiunge -n al comando clone originale, il comando read-tree provoca il seguente errore:

errore: checkout sparso non lascia alcuna voce nella directory di lavoro

Come si può fare il checkout sparse senza prima verificare tutti i file?



Nota: git worktree add --no-checkoutfunzionerà anche (non solo git clone --no-checkout) con git 2.9 (solo 2016). Vedi la mia risposta qui sotto
VonC

Dopo aver provato tutte le soluzioni qui, l'unica che scarica solo la directory (senza spingere in seguito!) È questa .
LondonRob

Risposte:


24

Nel 2020 esiste un modo più semplice per gestire il checkout sparse senza doversi preoccupare dei file .git. Ecco come l'ho fatto:

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

Si noti che richiede l'installazione della versione 2.25 di git. Maggiori informazioni qui: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/

AGGIORNARE:

Il git clonecomando sopra clonerà comunque il repository con la sua cronologia completa, anche se senza estrarre i file. Se non hai bisogno della cronologia completa, puoi aggiungere il parametro --depth al comando, in questo modo:

# create a shallow clone,
# with only 1 (since depth equals 1) latest commit in history
git clone <URL> --no-checkout <directory> --depth 1

1
Questo è vero, buon punto. Upvoted. Ho seguito la sparse-checkout --conefunzione in stackoverflow.com/a/59515426/6309
VonC

Varrebbe la pena aggiungere un clone parziale ( --filter) alla tua risposta qui.
Tao,

@ alexey-grinko, il primo comando doveva ancora clonare l'intero repository in questione, anche se non lo ha verificato ... Stavo cercando di risparmiare il tempo di non clonare tutte le cose che non mi servono .. .
mropp

1
@mropp, ho aggiornato la risposta aggiungendo un --depthparametro che ci consente di eseguire un clone superficiale. Sarà di aiuto? @Tao, non sono sicuro di come utilizzare --filterin questo caso, non l'ho provato. Potresti fornire un esempio o pubblicare un'altra risposta a questo argomento?
Alexey Grinko,

4
nota che non funziona allo stesso modo nella versione 2.27 - non so perché.
Blazes

162

Si noti che questa risposta scarica una copia completa dei dati da un repository. Il git remote add -fcomando clonerà l'intero repository. Dalla pagina man digit-remote :

Con l' -fopzione, git fetch <name>viene eseguito immediatamente dopo l'impostazione delle informazioni remote.


Prova questo:

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

Ora scoprirai di avere un checkout "eliminato" con solo i file da path / Within_repo / to / desiderata_subdir presente (e in quel percorso).

Si noti che sulla riga di comando di Windows non è necessario citare il percorso, ovvero è necessario modificare il sesto comando con questo:

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

in caso contrario otterrai le virgolette nel file sparse-checkout e non funzionerà


3
Non riesco a usare il comando "git checkout [branchname]" (anche trovato errore: checkout sparso non lascia alcuna voce nella directory di lavoro). Ho usato "git pull origin master" e funziona correttamente.
Natty,

2
Con la versione 1.7.2.5 di git su Linux, ho ottenuto i seguenti risultati: echo 'dir / *' controlla solo i file in dir / ma non nei suoi sottodir; echo 'dir /' (no asterix!) controlla correttamente l'intero albero sotto dir /. HTH
pavek,

37
Questo semplicemente non ha funzionato per me - il comando "git remote" ha portato alla verifica dell'intero repository - bam! - bene allora; quindi "git config ..." e le specifiche di una sotto-directory di interesse nei seguenti comandi non hanno avuto effetto. L'URL del repository specificato nel comando "git remote" è solo il percorso del file .git di livello superiore? O dovrebbe essere un percorso per il sottotrirettore di interesse?
Rob Cranfill,

10
ecco una versione semplificata (non è necessario creare manualmente la directory, fare un init e aggiungere in remoto, basta fare il normale git clone + ciclo di checkout con l'opzione --no-checkout come menzionato da @onionjake): git clone --no-checkout <progetto> cd <progetto> echo <dir>> .git / info / sparse-checkout git checkout <branch>
Gregor

22
Il git remote addcomando scarica tutto perché è quello che -ffa - gli dice di recuperare immediatamente, prima di aver definito le opzioni di checkout sparse. Ma omettere o riordinare ciò non aiuta. I checkout sparsi riguardano solo l'albero di lavoro, non il repository. Se invece vuoi che il tuo repository segua una dieta, allora devi guardare le opzioni --deptho --single-branch.
Miral,

43

Git clone ha un'opzione ( --no-checkouto -n) che fa quello che vuoi.

Nel tuo elenco di comandi, basta modificare:

git clone <path>

A questa:

git clone --no-checkout <path>

È quindi possibile utilizzare la cassa sparsa come indicato nella domanda.


7
sì, non effettua un checkout, ma esegue comunque un download per scaricare l'intera cronologia dei repository
Jason S,

9
@JasonS la domanda era specificamente di non fare un checkout. Se non si desidera quindi l'intera cronologia utilizzare l' --depth <depth>opzione sul clone git. Ciò scaricherà solo gli ultimi <depth>commit dalla cronologia. Attualmente non è possibile scaricare parzialmente un singolo commit con git, sebbene se il telecomando lo supporta è possibile utilizzare git archive --remoteper scaricare set parziali di file.
onionjake,

Ora puoi anche "estrarre" un commit senza scaricare alcun file utilizzando vfsforgit.org . Questo potrebbe essere utile se qualcuno sta provando a fare il checkout solo di un piccolo sottoinsieme di un singolo commit.
onionjake,

22

Avevo un caso d'uso simile, tranne che volevo fare il checkout solo del commit per un tag e potare le directory. L'uso lo --depth 1rende veramente scarso e può davvero velocizzare le cose.

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
--depth 1 è chiamato clone superficiale, solo FYI.
Mark Allison,

1
Questo ha aiutato! Grazie
kp123

1
Grazie per questo. Ho capito bene dopo aver provato molti altri modi per impedire il download dell'intero repository.
J ... S,

12

Ho trovato la risposta che cercavo nel one-liner pubblicato in precedenza da pavek (grazie!), Quindi volevo fornire una risposta completa in un'unica risposta che funziona su 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

Ho cambiato un po 'l'ordine dei comandi, ma questo non sembra avere alcun impatto. La chiave è la presenza della barra finale "/" alla fine del percorso nel passaggio 5.


3
sei sicuro che sia quello che vuoi? -f significa recuperare tutti i dati, ottenere comunque tutte le altre informazioni che non si desidera ed è lento. (Questo è ancora "controllare l'intero repository")
Shuman

1
Ho provato i passaggi precedenti in Windows, ma il checkout di riserva non funziona nel prompt dei comandi, quindi ho provato la shell Git Bash e ha funzionato !!. il prompt dei comandi è in grado di eseguire tutti i comandi git come push, pull etc ma quando si tratta di checkout sparso non riesce.
user593029,

Come fare solo i file della sottodirectory. Voglio solo recuperare i file all'interno di una specifica sottodirectory.
Babish Shrestha,

@BabishShrestha vedi commento di onionjake su altra risposta FWIW: |
rogerdpack,

9

Purtroppo nessuno dei precedenti ha funzionato per me, quindi ho trascorso molto tempo a provare diverse combinazioni di sparse-checkoutfile.

Nel mio caso, volevo saltare le cartelle con le configurazioni IntelliJ IDEA.

Ecco cosa ho fatto:


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

Correre git config core.sparsecheckout true

Creato .git\info\sparse-checkoutcon il seguente contenuto

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

Esegui 'git checkout -' per ottenere tutti i file.


La cosa fondamentale per farlo funzionare era aggiungere /*il nome della cartella.

Ho git 1.9


3
No, scarica ancora tutto, tutti i commit e tutti i file, git 2.3.2
Tyguy7

6
I checkout sparsi riguardano solo l'albero di lavoro. Non influiscono sulla dimensione del repository o su ciò che viene recuperato. Hai bisogno di diverse opzioni se lo desideri.
Miral,

Prova Git Bash Shell la prossima volta se lavori in Windows e usa i passaggi precedenti di 'pbetkier' funziona bene
user593029

6

Sì, è possibile scaricare una cartella invece di scaricare l'intero repository. Anche qualsiasi / ultimo commit

Bel modo di farlo

D:\Lab>git svn clone https://github.com/Qamar4P/LolAdapter.git/trunk/lol-adapter -r HEAD
  1. -r HEAD scaricherà solo l'ultima revisione, ignorando tutta la cronologia.

  2. Nota trunk e / cartella specifica

Copia e modifica l'URL prima e dopo /trunk/. Spero che questo possa aiutare qualcuno. Godere :)

Aggiornato il 26 set 2019


applicabile solo per coloro che provengono o utilizzano svn. Non voterà questo.
C Johnson,

@CJohnson come puoi vedere, sto clonando la cartella repository git. Funziona bene
Qamar,

1
Nota che questo non è qualcosa che git offre immediatamente, ma è qualcosa che l' hub Git offre adiacente alla normale offerta Git. Tuttavia, funziona magnificamente quando è possibile utilizzarlo. Grazie!
Qix - MONICA È STATA MISTREATA il

1
Tra la miriade di suggerimenti su SO, la tua è la soluzione più concisa e chiara.
boardrider,

5

Risposta aggiornata 2020:

Ora c'è un comando git sparse-checkout, che presento in dettaglio con Git 2.25 (Q1 2020)

La risposta di nicono ne illustra l'utilizzo:

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

Si è evoluto con Git 2.27 e sa come "riapplicare" un checkout sparso, come qui .
Nota che con Git 2.28 git statusmenzionerai che sei in un repository con check-out sparso

Risposta originale: 2016

git 2.9 (giugno 2016) generalizzerà l' --no-checkoutopzione a git worktree add(il comando che consente di lavorare con più alberi di lavoro per un repository )

Vedi commit ef2a0ac (29 mar 2016) di Ray Zhang ( OneRaynyDay) .
Aiutato da: Eric Sunshine ( sunshineco) e Junio ​​C Hamano ( gitster) .
(Unita da Junio ​​C Hamano - gitster- in commit 0d8683c , 13 apr 2016)

La git worktreepagina man ora include:

--[no-]checkout:

Per impostazione predefinita, addi controlli fuori <branch>, tuttavia, --no-checkoutpossono essere utilizzati per sopprimere cassa al fine di rendere le personalizzazioni, come la configurazione radi-checkout .


4

I passaggi per sparse checkout solo cartella specifica:

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]

Cordiali saluti, nel primo (1) passaggio, non è necessario utilizzare --no-checkout. Basta clonare l'intero repository e quindi eseguire tutti i passaggi seguenti 2-5 (menzionati sopra), otterrai l'output desiderato. Fammi sapere se non l'hai capito.
SANDEEP MACHIRAJU,

4

Sulla base di questa risposta di apenwarr e di questo commento di Miral, ho trovato la seguente soluzione che mi ha permesso di risparmiare quasi il 94% dello spazio su disco durante la clonazione locale del repository linux git mentre desideravo solo una sottodirectory Documentation:

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

Quindi sono sceso da 2,9 GB a 182 MB, il che è già abbastanza bello.

Tuttavia, non ho fatto in modo che funzionasse git clone --depth 1 --no-checkout --filter=blob:none file:///…/linux linux-sparse-test( suggerito qui ) poiché i file mancanti sono stati tutti aggiunti come file rimossi all'indice. Quindi, se qualcuno conosce l'equivalente di git clone --filter=blob:nonefor git fetch, probabilmente possiamo risparmiare qualche megabyte. (La lettura della pagina man di git-rev-listsuggerisce anche che c'è qualcosa del genere --filter=sparse:path=…, ma neanche io ho funzionato.

(Tutti hanno provato con git 2.20.1 da Debian Buster.)


1
Feedback interessante. Upvoted. Neanche io conosco --filter=sparse:path=….
VonC

3

Sono nuovo di Git ma sembra che se eseguo il checkout di Git per ogni directory, allora funziona. Inoltre, il file sparse-checkout deve avere una barra finale dopo ogni directory come indicato. Qualcuno in più di esperienza conferma che funzionerà.

È interessante notare che se si esegue il checkout di una directory che non si trova nel file sparse-checkout sembra non fare alcuna differenza. Non si presentano nello stato git e git read-tree -m -u HEAD non provoca la sua rimozione. git reset --hard non causa la rimozione della directory. Qualcuno ha più esperienza nel commentare cosa pensa git delle directory che sono state estratte ma che non sono nel file di checkout sparso?


1

In git 2.27, sembra che il checkout di git sparse si sia evoluto. La soluzione in questa risposta non funziona esattamente allo stesso modo (rispetto a 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

Questi comandi hanno funzionato meglio:

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

Vedi anche: git-clone --sparse e git-sparse-checkout add


1
Buon aggiornamento. Upvoted. Ho modificato la mia risposta di conseguenza. Ho presentato questo comando nel dicembre 2019: stackoverflow.com/a/59515426/6309
VonC

0

Nel mio caso, voglio saltare la Podscartella durante la clonazione del progetto. Ho fatto un passo alla volta come sotto e funziona per me. Spero che sia d'aiuto.

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

Promemoria, se si desidera saltare più cartelle, è sufficiente aggiungere più riga nel file di controllo sparse.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.