git działa bardzo wolno podczas śledzenia dużych plików binarnych

84

Mój projekt ma sześć miesięcy, a git działa bardzo wolno. Śledzimy około 30 plików o rozmiarze od 5 MB do 50 MB. To są pliki binarne i trzymamy je w git. Uważam, że te pliki spowalniają git.

Czy istnieje sposób na zabicie wszystkich plików o rozmiarze> 5 MB z repozytorium. Wiem, że straciłbym wszystkie te pliki i nie mam nic przeciwko.

Idealnie chciałbym otrzymać polecenie, które zawierałoby listę wszystkich dużych plików (> 5 MB). Widzę listę, a potem mówię ok, usuń te pliki i przyspiesz git.

Powinienem wspomnieć, że git działa wolno nie tylko na moim komputerze, ale wdrożenie aplikacji w środowisku przejściowym zajmuje teraz około 3 godzin.

Zatem poprawką powinno być coś, co wpłynie na serwer, a nie tylko na użytkowników repozytorium.

Nick Vanderbilt
źródło
4
Możesz spróbować użyć gita z git-bigfilesprojektu
Jakub Narębski
1
możesz spróbować użyć czegoś takiego jak git-Annex do zarządzania plikami binarnymi. git-annex.branchable.com
Jed Schneider
Na wypadek, gdyby było to przydatne dla każdego, dodam, że moja wersja gita dla Cygwin wisiała na rebases. Kiedy używałem Git-Bash, to samo repozytorium nie miało żadnych problemów.
Sridhar Sarnobat,
Zastanawiam się, czy nadal tak jest. Mam nadzieję, że wyłączą kompresję dla wszystkiego, gdzie efekt kompresji jest poniżej 50% (lub jakikolwiek inny możliwy do wyboru X%). W pewnym momencie prędkość wyraźnie przewyższa przestrzeń sprzętową!
Trilarion

Odpowiedzi:

125

Czy zbierasz śmieci?

git gc

To powoduje znaczną różnicę w szybkości, nawet w przypadku małych repozytoriów.

kubi
źródło
8
Odbywa się to automatycznie, gdy jest zbyt dużo bałaganu. Wątpię, żeby to naprawdę pomogło OP.
Cascabel
@Jefromi, czy to nowe? Właśnie wczoraj zaktualizowałem do 1.7.1, ale wcześniej wersja, której używałem, zdecydowanie nie uruchamiała się automatycznie gc.
kubi
@kubi: Cóż, nie istnieje od zawsze, ale nie jest do końca nowy - został wywołany z commit, merge, am i rebase od czasu caf9de2 (14 września 2007) lub w stabilnej wersji 1.5.4 (1 lutego 2008 ).
Cascabel
1
Po namyśle, git gcprawdopodobnie nie można go wezwać, commita mergeinaczej git fsck --unreachablenigdy niczego nie zwróci.
kubi
4
Znalazłem to. Domyślna liczba luźnych obiektów przed automatycznym gcuruchomieniem to 6700, co wyjaśnia, dlaczego nigdy nie widziałem, aby działał.
kubi
79

Wyjaśnienie

Git jest naprawdę dobry w ogromnych historiach małych plików tekstowych, ponieważ może efektywnie przechowywać je i ich zmiany. Jednocześnie git bardzo źle radzi sobie z plikami binarnymi i naiwnie przechowuje oddzielne kopie pliku ( przynajmniej domyślnie ). Repozytorium staje się ogromne, a potem zwolnione, jak zauważyłeś.

Jest to powszechny problem wśród DVCS, pogarszany przez fakt, że pobierasz każdą wersję każdego pliku („całe repozytorium”) za każdym razem, gdy klonujesz. Faceci z Kiln pracują nad wtyczką, która będzie traktować te duże pliki bardziej jak Subversion, która pobiera tylko historyczne wersje na żądanie.

Rozwiązanie

To polecenie wyświetli listę wszystkich plików w bieżącym katalogu o rozmiarze> = 5 MB.

find . -size +5000000c 2>/dev/null -exec ls -l {} \;

Jeśli chcesz usunąć pliki z całej historii repozytorium, możesz skorzystać z tego pomysłu, aby przejrzeć git filter-branchhistorię i pozbyć się wszelkich śladów dużych plików. Po wykonaniu tej czynności wszystkie nowe klony repozytorium będą szczuplejsze. Jeśli chcesz rozbudować repozytorium bez klonowania, znajdziesz wskazówki na stronie podręcznika (zobacz „Lista kontrolna zmniejszania repozytorium”).

git filter-branch --index-filter \
    'find . -size +5000000c 2>/dev/null -exec git rm --cached --ignore-unmatch {} \;'

Słowo ostrzeżenia : spowoduje to, że repozytorium będzie niekompatybilne z innymi klonami, ponieważ drzewa i indeksy mają inne wpisane pliki; nie będziesz już w stanie ich odepchnąć ani wyciągnąć.

Andres Jaan Tack
źródło
4
Uwaga: to jest wersja narzędzia find dla systemów Unix / Linux, a nie find.exe dla systemu Windows.
Craig Trader
1
+1. Może chcesz findnajpierw wysłać wyjście do pliku, sprawdź listę, a następnie użyj git rm, na wypadek gdyby były jakieś fałszywe trafienia. Możesz też sprawdzić git statuspo usunięciu dużych plików i użyć funkcji, git checkout HEAD <file>aby odzyskać wszystkie omyłkowo usunięte pliki.
Cascabel
2
Myślę, że twój komentarz, że git "domyślnie przechowuje oddzielne kopie" jest wstecz. Zgodnie z łańcuchem e-maili, z którym łączyłeś się ( thread.gmane.org/gmane.comp.version-control.git/146957/… ) domyślnie, git próbuje porównać pliki binarne - i właśnie to powoduje problem; nie magazyn.
Alexander Bird,
16

Oto ocenzurowana wersja, która ma być mniej negatywna i podżegająca:

Git ma dobrze znaną słabość, jeśli chodzi o pliki, które nie są plikami tekstowymi wiersz po wierszu. Obecnie nie ma rozwiązania i nie ogłoszono żadnych planów rozwiązania tego problemu przez główny zespół git. Istnieją obejścia, jeśli projekt jest mały, powiedzmy 100 MB lub więcej. Istnieją gałęzie projektu git, które rozwiązują ten problem ze skalowalnością, ale te gałęzie nie są w tej chwili dojrzałe. Niektóre inne systemy kontroli wersji nie mają tego konkretnego problemu. Powinieneś rozważyć tę kwestię jako jeden z wielu czynników przy podejmowaniu decyzji, czy wybrać git jako swój system kontroli wersji.

Jan
źródło
8
„Git ma dobrze znaną słabość…” - potrzebne źródło
Nav
6
Wiem to. kto potrzebuje cytatów, kiedy jego aktualna wiedza powszechna. po prostu nie używaj gita do binarnego. korzystać z konieczności lub specjalistycznego zarządzania aktywami.
v.oddou,
1
@ v.oddou Cóż, istnieje różnica między „Wiem to” a „Jego faktyczną wiedzą powszechną”. Chodzi o to, że nie wszyscy o tym wiedzą i prawdopodobnie nie jest to nawet do końca prawdą. Więc każdy rodzaj cytatu poprawia tę odpowiedź. Jest w porządku, ale na pewno nie jest wybitny i ma kopię zapasową.
Trilarion
2
Cóż, nie po to, aby dodać paliwa do ognia, ale jeśli wyszukujesz w Google „git i pliki binarne wolno”, znajduje się wiele linków, które zgłaszają użytkownikom problemy z zarządzaniem plikami binarnymi w git. Ponadto programiści, którzy używają jednego lub drugiego SCM, znają mocne i słabe strony każdego systemu ... więc git zyskał reputację bardzo powolnego, gdy pliki binarne są wrzucane do repozytorium.
AhiyaHiya
We wszystkich początkowych zasobach, z których korzystałem, git jest zły z plikami binarnymi. git-Annex istnieje, aby to naprawić. git jest świetny, ale nie dla danych binarnych. Dobrze byłoby utworzyć link do forków dodających funkcje binarne, aby ludzie mogli wesprzeć pracę.
fuzzyTew
15

Nie ma nic szczególnego na temat plików binarnych i sposobu, w jaki git je obsługuje. Kiedy dodajesz plik do repozytorium git, dodawany jest nagłówek, a plik jest kompresowany za pomocą zlib i zmienia nazwę po skrócie SHA1. To jest dokładnie to samo, niezależnie od typu pliku. W kompresji zlib nie ma nic, co mogłoby powodować problemy w przypadku plików binarnych.

Ale w niektórych punktach (pushing, gc) Git zaczyna rozważać możliwość kompresji zawartości delta. Jeśli git znajdzie pliki, które są podobne (nazwa pliku itp.), Umieszcza je w pamięci RAM i zaczyna kompresować je razem. Jeśli masz 100 plików i każdy z nich przypisze 50 MB, spróbuje jednocześnie umieścić w pamięci 5 GB. Do tego musisz dodać trochę więcej, aby wszystko działało. Komputer może nie mieć takiej ilości pamięci RAM i zaczyna się wymieniać. Ten proces wymaga czasu.

Możesz ograniczyć głębokość kompresji delta, aby proces nie zużywał tak dużo pamięci, ale w rezultacie kompresja jest mniej wydajna. (core.bigFileThreshold, atrybut delta, pack.window, pack.depth, pack.windowMemory itp.)

Jest więc wiele rzeczy, które możesz zrobić, aby git działał bardzo dobrze z dużymi plikami.

jaskółka oknówka
źródło
4
Zobacz tutaj wyjaśnienie, jak wyłączyć te próby „delta”.
Alexander Bird
6

Jednym ze sposobów przyspieszenia działania jest użycie --depth 1flagi. Zobacz stronę podręcznika po szczegóły. Nie jestem wielkim guru od gitów, ale uważam, że to mówi rób odpowiednik a p4 getlub an svn get, to znaczy daje tylko najnowsze pliki zamiast „podaj mi wszystkie wersje wszystkich plików przez cały czas”, co jest co git clonerobi.

David
źródło
1
To nie pozwala na wypychanie z repozytorium, więc ma ograniczoną użyteczność.
Martin C. Martin
4

czy powiedziałeś gitowi, że te pliki są binarne?

np. dodane *.ext binarydo twojego repozytorium.gitattributes

sml
źródło
Zakładam, że mówienie gitowi, że pliki są binarne, przyspiesza.
Nick Vanderbilt
może to zrobić, jeśli heurystyka gita nie może automatycznie stwierdzić, że plik jest binarny.
sml
2

Używam Gita od 2008 roku zarówno w systemie Windows, jak i GNU / linux i większość plików, które śledzę, to pliki binarne. Niektóre z moich repozytoriów mają kilka GB i zawierają pliki JPEG i inne nośniki. Mam wiele komputerów zarówno w domu, jak iw pracy z systemem Git.

Nigdy nie miałem objawów opisanych w oryginalnym poście. Ale zaledwie kilka tygodni temu zainstalowałem MsysGit na starym laptopie z Win-XP i prawie wszystko, co zrobiłem, zatrzymało Gita. Nawet test z dwoma lub trzema małymi plikami tekstowymi był absurdalnie wolny. Mówimy o około 10 minutach, aby dodać plik mniej niż 1k ... wygląda na to, że procesy git pozostały żywe na zawsze. Wszystko inne działało zgodnie z oczekiwaniami na tym komputerze.
Zdegradowałem coś z najnowszej wersji do 1.6 i problemy zniknęły ...
Mam inne laptopy tej samej marki, również z Win-XP zainstalowanym przez ten sam dział IT z tego samego obrazu, gdzie Git działa dobrze niezależnie od wersji. .. Więc musi być coś dziwnego z tym konkretnym komputerem.

Zrobiłem również kilka testów z plikami binarnymi i kompresją. Jeśli masz obraz BMP i wprowadzasz w nim małe zmiany i zatwierdzasz je, git gc skompresuje się bardzo dobrze. Mój wniosek jest taki, że kompresja nie zależy od tego, czy pliki są binarne, czy nie.

jaskółka oknówka
źródło
-2

Po prostu ustaw pliki tak, aby były ignorowane. Zobacz link poniżej:

http://help.github.com/git-ignore/

joshlrogers
źródło
@Jefromi właściwie, jeśli spojrzysz na link, który zamieściłem, zobaczysz, że w drugim akapicie znajdują się instrukcje, które mówią mu dokładnie, co zrobić w takim przypadku.
joshlrogers
14
Prawdziwe. Jednak bezpośrednia treść Twojej odpowiedzi brzmi „zignoruj ​​pliki”, a nie „usuń pliki ze śledzenia, a następnie je zignoruj”. Generalnie lepiej jest napisać to tutaj niż zamieścić link do innej witryny.
Cascabel
-24

To dlatego, że git nie jest skalowalny.

Jest to poważne ograniczenie w git, które jest zagłuszane przez poparcie git. Przeszukaj listy mailingowe git, a znajdziesz setki użytkowników zastanawiających się, dlaczego zaledwie 100 MB obrazów (powiedzmy, na stronę internetową lub aplikację) rzuca gita na kolana. Problem polega na tym, że prawie cały git polega na optymalizacji, którą nazywają „pakowaniem”. Niestety, pakowanie jest nieefektywne dla wszystkich oprócz najmniejszych plików tekstowych (tj. Kodu źródłowego). Co gorsza, staje się coraz mniej wydajny wraz z rozwojem historii.

To naprawdę żenująca wada w git, która jest reklamowana jako „szybka” (pomimo braku dowodów), a programiści gita są tego świadomi. Dlaczego tego nie naprawili? Na liście mailingowej git znajdziesz odpowiedzi od programistów git, którzy nie rozpoznają problemu, ponieważ ich dokumenty programu Photoshop (* .psd) mają zastrzeżony format. Tak, naprawdę jest tak źle.

Oto wynik:

Użyj git do małych projektów zawierających tylko kod źródłowy, dla których nie masz ochoty konfigurować oddzielnego repozytorium. Lub w przypadku małych projektów zawierających tylko kod źródłowy, w których chcesz skorzystać z modelu zdecentralizowanego tworzenia kopii całego repozytorium git. Lub gdy po prostu chcesz nauczyć się nowego narzędzia. To wszystko są dobre powody, dla których warto używać git, a nauka nowych narzędzi zawsze sprawia przyjemność.

Nie używaj git, jeśli masz dużą bazę kodu, pliki binarne, ogromną historię itp. Tylko jedno z naszych repozytoriów to TB. Git nie może tego znieść. VSS, CVS i SVN radzą sobie dobrze. (Jednak SVN nadyma się).

Daj też dajowi czas na dojrzewanie. Nadal jest niedojrzały, ale ma dużo rozpędu. Myślę, że z czasem praktyczna natura Linusa przezwycięży purystów OSS, a git w końcu będzie przydatny w szerszej dziedzinie.

Jan
źródło
15
Ta odpowiedź jest naprawdę zbyt negatywna i zapalna. Tak, git ma problemy ze skalowalnością plików binarnych . Jest dość skalowalny i szybki dla kodu. Istnieje wiele dowodów na szybkość (pomimo twojego twierdzenia przeciwnego), nawet pomijając fakt, że CVS / SVN wymagają dostępu do sieci zamiast dostępu do dysku dla wielu operacji. Istnieje wiele dużych projektów z ogromną historią, które całkiem szczęśliwie wykorzystują git.
Cascabel
8
I ... Twoje gadanie o Photoshopie? Nie zamierzam tracić czasu na pisanie szczegółowej odpowiedzi, ale czytając cały wątek thread.gmane.org/gmane.comp.version-control.git/146957/ ... (może jesteś zirytowany, ponieważ John w Wątek to ty?), widzę wiele rozsądnych odpowiedzi na temat tego, jak najlepiej sobie z tym poradzić z obecnym gitem, jak można to rozwiązać w przyszłości i dlaczego nie jest to ich priorytet.
Cascabel
14
Tak, nie sądzę, że masz rację, tutaj. Git działa drogę zbyt dobrze dla jądra Linux zasługują lekceważąco, „nie jest skalowalne.”
Andres Jaan Tack
1
Ten komentarz byłby bardziej wiarygodny, gdyby zawierał linki lub dane umożliwiające jego kopię zapasową. A tak przy okazji, co myślisz o rtęciowej?
vy32
3
Może nie wyraża popularnej opinii, ale myślę, że głosowanie w dół było bardziej przesadne w swojej „negatywności” niż odpowiedź PO. Powinniśmy zachęcać do sprzeciwu, a nie kupować tylko dlatego, że komuś nie podoba się smak kontroli wersji tego roku. GIT naprawdę nie jest dobrze przystosowany do śledzenia plików binarnych. Ale działa świetnie w przypadku kodu źródłowego, jest to główny cel, dlatego świetnie radzi sobie z jądrem Linuksa.
dyasta