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?



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

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


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.


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>

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.


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


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


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 .


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]

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


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?


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.