Czy można wykonać rzadkie pobieranie bez uprzedniego sprawdzenia całego repozytorium?

171

Pracuję z repozytorium z bardzo dużą liczbą plików, których wypisanie zajmuje kilka godzin. Zastanawiam się, czy Git działałby dobrze z tego rodzaju repozytorium teraz, gdy obsługuje rzadkie pobrania, ale każdy przykład, który mogę znaleźć, robi następujące rzeczy:

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

Problem z tą sekwencją poleceń polega na tym, że oryginalny klon również wykonuje pobieranie. Jeśli dodasz -n do oryginalnego polecenia clone, polecenie odczytu drzewa spowoduje następujący błąd:

błąd: Rzadkie wyewidencjonowywanie nie pozostawia żadnego wpisu w katalogu roboczym

Jak można wykonać rzadkie wyewidencjonowanie bez uprzedniego wyewidencjonowania wszystkich plików?

dromodel
źródło
Uwaga: git worktree add --no-checkoutbędzie działać również (nie tylko git clone --no-checkout) z git 2.9 (tylko 2016). Zobacz moją odpowiedź poniżej
VonC,
Po wypróbowaniu wszystkich rozwiązań tutaj, jedynym, który po prostu pobiera katalog (bez późniejszego wciskania!), Jest to .
LondonRob

Odpowiedzi:

24

W 2020 roku istnieje prostszy sposób radzenia sobie z rzadkim pobieraniem pieniędzy bez martwienia się o pliki .git. Oto jak to zrobiłem:

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

Zauważ, że wymaga zainstalowanego gita w wersji 2.25. Przeczytaj więcej na ten temat tutaj: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/

AKTUALIZACJA:

Powyższe git clonepolecenie nadal sklonuje repozytorium wraz z jego pełną historią, ale bez sprawdzania plików. Jeśli nie potrzebujesz pełnej historii, możesz dodać parametr --depth do polecenia, na przykład:

# 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
źródło
1
To prawda, słuszna uwaga. Głosowano za. Śledziłem sparse-checkout --conefunkcję na stackoverflow.com/a/59515426/6309
VonC
Warto byłoby tutaj dodać częściowe clone ( --filter) do odpowiedzi.
Tao
@ alexey-grinko, pierwsze polecenie nadal musiało sklonować całe repozytorium, o którym mowa, nawet jeśli go nie sprawdzało ... Chciałem zaoszczędzić czas, nie klonując wszystkich rzeczy, których nie potrzebuję. ,
mropp
1
@mropp, zaktualizowałem odpowiedź, dodając --depthparametr, który pozwala nam zrobić płytki klon. Czy to pomoże? @Tao, nie jestem pewien, jak użyć --filterw tym przypadku, nie próbowałem. Czy mógłbyś podać przykład lub opublikować inną odpowiedź na ten temat?
Alexey Grinko
4
zauważ, że nie działa to tak samo w wersji 2.27 - nie wiem dlaczego.
Blazes
162

Należy pamiętać, że ta odpowiedź powoduje pobranie pełnej kopii danych z repozytorium. git remote add -fPolecenie sklonowania całego repozytorium. Ze strony podręcznika mangit-remote :

Z -fopcją, git fetch <name>jest uruchamiany natychmiast po skonfigurowaniu informacji zdalnych.


Spróbuj tego:

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

Teraz zobaczysz, że masz „przycięte” pobranie z obecnymi tylko plikami z path / within_repo / to / allowed_subdir (i w tej ścieżce).

Zauważ, że w linii poleceń Windows nie możesz cytować ścieżki, tzn. Musisz zmienić szóste polecenie na to:

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

jeśli nie, otrzymasz cudzysłowy w pliku sparse-checkout i to nie zadziała

apenwarr
źródło
3
Nie mogę użyć polecenia „git checkout [nazwa gałęzi]” (znaleziono również błąd: Rzadkie pobieranie nie pozostawia żadnego wpisu w katalogu roboczym). Użyłem „git pull origin master” i działa poprawnie.
Natty,
2
W przypadku gita w wersji 1.7.2.5 w systemie Linux otrzymałem następujące wyniki: echo 'dir / *' pobiera tylko pliki w katalogu dir /, ale nie w jego podkatalogach; echo 'dir /' (bez gwiazdki!) poprawnie sprawdza całe drzewo w katalogu dir /. HTH
pavek
37
To po prostu nie zadziałało dla mnie - polecenie „git remote” spowodowało wyewidencjonowanie całego repozytorium - bam! - w takim razie; więc "git config ..." i specyfikacja podkatalogu będącego przedmiotem zainteresowania w poniższych poleceniach nie przyniosły efektu. Czy adres URL repozytorium określony w poleceniu „git remote” to tylko ścieżka do pliku .git najwyższego poziomu? A może powinna to być ścieżka do interesującego nas pod-katalogu?
Rob Cranfill,
10
oto usprawniona wersja (nie ma potrzeby ręcznego tworzenia katalogu, wykonywania init i zdalnego dodawania, po prostu wykonaj normalny cykl git clone + checkout z opcją --no-checkout, jak wspomniano w @onionjake): git clone --no-checkout <project> cd <project> echo <dir>> .git / info / sparse-checkout git checkout <branch>
Gregor
22
git remote addPliki do pobrania dowodzenia wszystko dlatego, że to, co -frobi - mówi ona natychmiast sprowadzić, zanim pan określił rozrzedzone opcje kasie. Ale pominięcie lub zmiana kolejności to nie pomoże. Rzadkie pobrania dotyczą tylko drzewa roboczego, a nie repozytorium. Jeśli zamiast tego chcesz, aby twoje repozytorium przeszło na dietę, musisz zamiast tego spojrzeć na opcje --depthlub --single-branch.
Miral
43

Klon Git ma opcję ( --no-checkoutlub -n), która robi to, co chcesz.

Na liście poleceń po prostu zmień:

git clone <path>

Do tego:

git clone --no-checkout <path>

Następnie możesz skorzystać z rzadkiej płatności zgodnie z pytaniem.

cebula
źródło
7
tak, nie dokonuje płatności, ale nadal pobiera całą historię repozytorium
Jason S
9
@JasonS pytanie dotyczyło w szczególności nie robienia kasy. Jeśli nie chcesz, całą historię użyj --depth <depth>opcji na git clone. Spowoduje to pobranie tylko ostatnich <depth>zatwierdzeń z historii. Obecnie nie ma sposobu na częściowe pobranie pojedynczego zatwierdzenia za pomocą git, chociaż jeśli twój pilot go obsługuje, możesz użyćgit archive --remote do pobrania częściowych zestawów plików.
cebula,
Możesz teraz także „wypisać” zatwierdzenie bez pobierania plików za pomocą wypisać vfsforgit.org . Może to być przydatne, jeśli ktoś próbuje pobrać tylko niewielki podzbiór pojedynczego zatwierdzenia.
cebula
22

Miałem podobny przypadek użycia, z wyjątkiem tego, że chciałem pobrać tylko zatwierdzenie dla tagu i wyczyścić katalogi. Używanie --depth 1sprawia, że ​​jest to naprawdę rzadkie i może naprawdę przyspieszyć działanie.

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
źródło
3
--depth 1 nazywa się płytkim klonem, po prostu FYI.
Mark Allison
1
To pomogło! Dziękuję
kp123
1
Dzięki za to. Zrobiłem to dobrze po wypróbowaniu wielu innych sposobów, aby zapobiec pobieraniu całego repozytorium.
J ... S
12

Znalazłem odpowiedź, której szukałem, z jednej linijki opublikowanej wcześniej przez pavek (dzięki!), Więc chciałem udzielić pełnej odpowiedzi w jednej odpowiedzi, która działa w systemie 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

Zmieniłem nieco kolejność poleceń, ale nie wydaje się to mieć żadnego wpływu. Kluczem jest obecność końcowego ukośnika „/” na końcu ścieżki w kroku 5.

JF Bergeron
źródło
3
czy na pewno tego chcesz? -f oznacza pobieranie wszystkich danych, nadal otrzymujesz wszystkie inne informacje, których nie chcesz, i jest to powolne. (To wciąż „sprawdzanie całego repozytorium”)
Shuman
1
Wypróbowałem powyższe kroki w systemie Windows, ale zapasowe pobranie nie działa w wierszu poleceń, więc wypróbowałem powłokę Git Bash i zadziałało !!. wiersz poleceń jest w stanie wykonać wszystkie polecenia git, takie jak push, pull itp., ale w przypadku rzadkiego pobierania kończy się niepowodzeniem.
user593029
Jak zrobić tylko pliki z podkatalogu. Chcę tylko pobrać pliki z określonego podkatalogu.
Babish Shrestha
@BabishShrestha zobacz komentarz cebulijake do innej odpowiedzi FWIW: |
rogerdpack
9

Niestety żadna z powyższych nie zadziałała, więc spędziłem bardzo dużo czasu próbując różnych kombinacji sparse-checkoutplików.

W moim przypadku chciałem pominąć foldery z konfiguracjami IntelliJ IDEA.

Oto co zrobiłem:


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

Biegać git config core.sparsecheckout true

Utworzono .git\info\sparse-checkoutz następującą zawartością

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

Uruchom polecenie „git checkout -”, aby pobrać wszystkie pliki.


Aby to zadziałało, trzeba było dodać /*po nazwie folderu.

Mam git 1.9

ekspert
źródło
3
Nie, nadal pobiera wszystko, wszystkie zatwierdzenia i wszystkie pliki, git 2.3.2
Tyguy7
6
Rzadkie pobrania dotyczą tylko drzewa roboczego. Nie wpływają na rozmiar repozytorium ani na to, co jest pobierane. Jeśli chcesz, potrzebujesz różnych opcji.
Miral
Następnym razem wypróbuj Git Bash Shell, jeśli pracujesz w systemie Windows i wykonaj powyższe kroki przez `` pbetkier '', działa dobrze
user593029
6

Tak, możliwe jest pobranie folderu zamiast pobierania całego repozytorium. Nawet jakiekolwiek / ostatnie zatwierdzenie

Niezły sposób na zrobienie tego

D:\Lab>git svn clone https://github.com/Qamar4P/LolAdapter.git/trunk/lol-adapter -r HEAD
  1. -r HEAD pobierze tylko ostatnią wersję, zignoruje całą historię.

  2. Zanotuj trunk i / specific-folder

Skopiuj i zmień adres URL przed i po /trunk/. Mam nadzieję, że to komuś pomoże. Cieszyć się :)

Zaktualizowano 26 września 2019 r

Qamar
źródło
dotyczy tylko tych, którzy pochodzą z lub używają svn. Nie będzie popierać tego.
C Johnson
@CJohnson, jak widać, klonuję folder repozytorium git. Działa dobrze
Qamar
1
Pamiętaj, że nie jest to coś, co Git oferuje po wyjęciu z pudełka, ale jest to coś, co centrum Git oferuje obok zwykłej oferty Git. Jednak działa pięknie, gdy możesz go wykorzystać. Dzięki!
Qix - MONICA ZOSTAŁA POMYŚLNA
1
Spośród niezliczonych sugestii dotyczących SO, Twoje jest najbardziej zwięzłym i jasnym rozwiązaniem.
boardrider
4

git 2.9 (czerwiec 2016) uogólni --no-checkoutopcję git worktree add(polecenie, które pozwala na pracę z wieloma drzewami roboczymi dla jednego repozytorium )

Zobacz commit ef2a0ac (29 marca 2016) autorstwa Ray Zhang ( OneRaynyDay) .
Pomagali: Eric Sunshine ( sunshineco) i Junio ​​C Hamano ( gitster) .
(Scalone przez Junio ​​C Hamano - gitster- w zatwierdzeniu 0d8683c , 13 kwietnia 2016 r.)

git worktreeStrona podręcznika zawiera teraz:

--[no-]checkout:

Domyślnie addsprawdza się <branch>jednak, --no-checkoutmogą być wykorzystywane do tłumienia kasie w celu dostosowania, takich jak konfigurowanie rzadki-Checkout .

VonC
źródło
4

Kroki do rzadkiego wyewidencjonowania tylko określonego folderu:

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
źródło
FYI, w pierwszym (1) kroku nie musisz używać --no-checkout. Po prostu sklonuj całe repozytorium, a następnie wykonaj wszystkie poniższe kroki 2-5 (wspomniane powyżej), otrzymasz dane wyjściowe, które chcesz. Daj mi znać, jeśli tego nie rozumiesz.
SANDEEP MACHIRAJU
4

Na podstawie tej odpowiedzi przez apenwarr i ten komentarz przez Miral wymyśliłem następujący roztwór, który uratował mi prawie 94% miejsca na dysku podczas klonowania repozytorium git linux lokalnie, podczas gdy tylko chce jednego podkatalogu Dokumentacja:

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

Zeszłam więc z 2,9 GB do 182 MB, co już jest fajne.

Jednak nie udało mi się z tym zadziałać git clone --depth 1 --no-checkout --filter=blob:none file:///…/linux linux-sparse-test( wskazano tutaj ), ponieważ wtedy wszystkie brakujące pliki zostały dodane jako usunięte pliki do indeksu. Więc jeśli ktoś zna odpowiednik git clone --filter=blob:nonefor git fetch, prawdopodobnie możemy zaoszczędzić trochę więcej megabajtów. (Przeczytanie strony podręcznika podręcznika git-rev-listrównież wskazuje, że jest coś podobnego --filter=sparse:path=…, ale to też nie zadziałało.

(Wszyscy próbowali z git 2.20.1 z Debian Buster.)

Axel Beckert
źródło
1
Ciekawe opinie. Głosowano za. Ja też nie wiem --filter=sparse:path=….
VonC
3

Jestem nowy w git, ale wygląda na to, że jeśli wykonam git checkout dla każdego katalogu, to działa. Ponadto plik sparse-checkout musi mieć końcowy ukośnik po każdym wskazanym katalogu. Ktoś z większym doświadczeniem proszę potwierdzić, że to zadziała.

Co ciekawe, jeśli wyewidencjonujesz katalog, którego nie ma w pliku sparse-checkout, wydaje się, że nie ma to znaczenia. Nie pojawiają się w statusie git, a git read-tree -m -u HEAD nie powoduje usunięcia go. git reset --hard również nie powoduje usunięcia katalogu. Czy ktoś bardziej doświadczony chciałby skomentować, co myśli git o katalogach, które są wyewidencjonowane, ale których nie ma w rzadkim pliku checkout?

dromodel
źródło
0

W moim przypadku chcę pominąć Podsfolder podczas klonowania projektu. Zrobiłem krok po kroku jak poniżej i to działa dla mnie. Mam nadzieję, że to pomoże.

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

Notatka: Jeśli chcesz pominąć więcej folderów, po prostu dodaj więcej linii w pliku sparse-checkout.

eric long
źródło