Jak zmniejszyć folder .git

141

Moja obecna baza ma łączną wielkość ok. 200MB.

Ale mój folder .git ma niesamowity rozmiar 5 GB (!). Odkąd wypycham swoją pracę na serwer zewnętrzny, nie potrzebuję dużej lokalnej historii ...

Jak mogę zmniejszyć folder .git, aby zwolnić miejsce na moim notebooku? Czy mogę usunąć wszystkie zmiany starsze niż 30 dni?

bardzo dziękuję za pomoc :)

JMW
źródło
2
Czy możesz opublikować wynik git count-objects -v?
CB Bailey,
2
Możliwy duplikat Reduce git repository size
sds

Odpowiedzi:

117

nie powinieneś usuwać wszystkich zmian starszych niż 30 dni (myślę, że jest to w jakiś sposób możliwe wykorzystanie gita, ale naprawdę nie jest zalecane).

możesz zadzwonić git gc --aggressive --prune, co dokona czyszczenia pamięci w repozytorium i usunie stare obiekty. czy masz dużo plików binarnych (archiwa, obrazy, pliki wykonywalne), które często się zmieniają? te zwykle prowadzą do ogromnych folderów .git (pamiętaj, że git przechowuje migawki dla każdej wersji, a pliki binarne źle się kompresują)

knittl
źródło
35
W rzeczywistości git gc --aggressivejest uważana za złą praktykę. Lepiej go używać git repack -a -d --depth=250 --window=250.
Artefact2,
18
@knittl: absolutnie. Oto wiadomość od samego Linusa: gcc.gnu.org/ml/gcc/2007-12/msg00165.html
Artefact2,
4
@ artefact2: dzięki za link! Przeczytałem to, a Linus zwraca uwagę, że - agresywne nie użyje ponownie (dobrych) delt - które wydają się nie istnieć w tym pytaniu, ponieważ repozytorium jest ogromne. przejście na przepakowanie zajmie znacznie więcej czasu. git gc --aggressivewywołuje przepakowywanie z rozmiarem okna 250 (por. strona podręcznika) i głębokością 250 (por. kod źródłowy). - agresywny dodatkowo dodaje -fprzełącznik, aby wyrzucić i powtórzyć wszystkie poprzednie operacje delta (jak również wspomniano w linku)
knittl
1
Właśnie sprawdziłem repozytorium hg.nginx.org/nginx (RELEASE-1.4.0 to wskazówka) przy użyciu git-remote-hg i to dało repozytorium około 100 MB. Użycie git gc --aggressive --prunezmniejszyło to do 19 MB.
Lekensteyn
16
@ Artefact2 Twoje oświadczenie jest nieaktualne : Zwróć uwagę, ile lat ma ten post. W rzeczywistości tego samego dnia, w którym został opublikowany, dyskusja na liście dyskusyjnej zaowocowała następującym zatwierdzeniem: [..] Zatem parametry pakowania są obecnie takie same dla obu metod. . --prunenie jest również konieczne, ponieważ stało się to domyślne od czasu v1.5.5-rc0(zatwierdzenie 25ee973 , marzec 2008).
Lekensteyn
70

Oto, co twórca git Linus ma do powiedzenia na temat zmniejszania repozytorium git:

Odpowiednikiem „git gc --aggressive” - ale zrobionego * poprawnie * - jest zrobienie (na noc) czegoś takiego jak

   git repack -a -d --depth=250 --window=250

gdzie ta kwestia głębi dotyczy tego, jak głębokie mogą być łańcuchy delta (wydłuż je dla starej historii - jest to warte przestrzeni narzutu), a sprawa okna dotyczy tego, jak duże okno obiektu chcemy przeskanować każdy kandydat na deltę.

I tutaj możesz chcieć dodać flagę „-f” (która oznacza „porzuć wszystkie stare delty”, ponieważ teraz faktycznie próbujesz się upewnić, że ta faktycznie znajduje dobrych kandydatów.

źródło: http://gcc.gnu.org/ml/gcc/2007-12/msg00165.html

Czy to pozbędzie się danych binarnych, które są osierocone w moim repozytorium? „git repack” nie usunie obrazów ani danych binarnych, które wpisałeś do repozytorium, a następnie usunąłeś. Aby trwale usunąć tego rodzaju dane z repozytorium, musisz ponownie zapisać historię. Typowym tego przykładem jest przypadkowe sprawdzenie haseł w git. Możesz cofnąć się i usunąć niektóre pliki, ale wtedy musisz ponownie zapisać swoją historię od tego czasu do teraz, a następnie wymusić wypchnięcie nowego repozytorium do źródła.

David Dehghan
źródło
Dla mnie folder .git to około 1,5G. Próbowałem tego, ale otrzymałem następujący błąd. fatal: Out of memory, malloc failed (tried to allocate 39763130 bytes)
Miron
2
Czy po wykonaniu repacklokalnie, wykonaniu zatwierdzenia i wypchnięcia, zmniejszanie będzie również zdalne?
Timo
@David Dehghan: Hej, próbowałem tego z katalogu projektu, ale rozmiar folderu .git się nie zmienił. Czy jest to oczekiwane, czy muszę naciskać, aby zobaczyć zmiany? (przepraszam, niezbyt doświadczony z git.) Mam obraz / gif w repozytorium i popełniłem kilka razy różne wersje tego obrazu i przypuszczam, że zwiększyło to rozmiar .git.
giorgim
Cześć, niestety teraz w ten sposób można wyczyścić starą wersję binarną. Aby to zrobić, musisz ponownie napisać swoją historię, która jest w rzeczywistości skomplikowana. Oto kilka wskazówek
David
22

Wypróbowałem te, ale moje repozytorium było nadal bardzo duże. Problem polegał na tym, że przypadkowo wpisałem niektóre wygenerowane duże pliki. Po kilku poszukiwaniach znalazłem świetny tutorial, który ułatwia usuwanie dużych wygenerowanych plików. Ten samouczek pozwolił mi zmniejszyć moje repozytorium z 60 MB do <1 MB.

Steve Lorek, How to Shrink a Git Repository

Chris Hinshaw
źródło
4
Oto zarchiwizowana wersja na wypadek zgnilizny linków. Ta odpowiedź jest / była pomocna w przypadku repozytorium, na które natknąłem się, w którym zostały zatwierdzone pliki .exe i .zip, które
zwiększyły
9

5 GB w porównaniu z 200 MB to trochę dziwne. Spróbuj biec git gc.

Ale nie, jeśli nie podzielisz repozytorium na moduły, nie możesz zmniejszyć rozmiaru .gitkatalogu.

Każdy klon repozytorium git jest pełnoprawnym repozytorium, które może działać jako serwer. To podstawowa zasada rozproszonej kontroli wersji.

Šimon Tóth
źródło
3

Używam git bardziej jako mechanizmu synchronizacji niż do historii wersji. Więc moim rozwiązaniem tego problemu było upewnienie się, że wszystkie moje obecne źródła są w zadowalającym stanie, a następnie po prostu usuń .git i ponownie zainicjuj repozytoria. Rozwiązany problem z miejscem na dysku. :-) Historia minęła :-( Robię to, ponieważ moje repozytorium jest na małym kluczu USB. Nie chcę ani nie potrzebuję całej mojej historii. Gdybym miał metodę na skracanie historii, użyłbym tego.

Gdybym był zainteresowany zachowaniem mojej historii, zarchiwizowałbym bieżące repozytorium. W pewnym momencie później mogłem sklonować oryginalne repozytorium, skopiować wszystkie zmiany z nowego repozytorium (załóżmy, że nie zrobiłem zbyt wiele (żadnej) zmiany nazwy lub usunięcia). Następnie wykonaj jedno duże zatwierdzenie, które będzie reprezentowało wszystkie zmiany wprowadzone w nowym repozytorium jako pojedyncze zatwierdzenie w starym repozytorium. Czy można połączyć historie? Może gdybym użył gałęzi, a potem usunął niepotrzebne obiekty. (Nie wiem wystarczająco dużo o wewnętrznych elementach gita, żeby zacząć się tak wygłupiać).

Darrel Lee
źródło
1
Zamiast tego możesz po prostu użyć Dropbox w tym przypadku użycia. Robiłem to przez wiele lat.
Jonny
1

Wypróbowałem powyższe metody, nic nie działało w moim przypadku (gdzie przypadkowo zabiłem proces git podczas git push), więc w końcu musiałem usunąć repozytorium i sklonować je ponownie, a teraz folder .git ma normalny rozmiar.

GorvGoyl
źródło
Musiałem użyć tego samego rozwiązania, ponieważ mój dysk był pełny (folder .git był> 90 GB), więc nie mogłem nawet uruchomić przepakowania lub git gc!
Fl4v
spróbuj
wydać
0

Zmniejsz repozytorium Git, usuwając historię dzienników niektórych plików z .gitfolderu na podstawie ich ostatniej aktualizacji.

Napotkałem ten sam problem na moim komputerze lokalnym. Powodem było to, że usunąłem kilka ogromnych plików z mojego lokalnego i przekazałem je do centralnego repozytorium. Ale zdarzenie po git status, git fetchi git pull. .gitRozmiar mojego folderu to około 3 GB. później uruchomiłem następujące polecenie, aby zmniejszyć rozmiar .gitfolderu, biorąc pod uwagę pliki, które zmieniły się / wygasły miesiąc temu.

Komenda

$ git remote prune origin && git repack && git prune-packed && git reflog expire --expire=1.month.ago && git gc --aggressive

Git Polecenia i ich krótki opis:

  • git-prune - Usuń wszystkie niedostępne obiekty z bazy danych obiektów
  • git-repack - Spakuj rozpakowane obiekty do repozytorium
  • git-prune-packed - Usuń dodatkowe obiekty, które są już w plikach paczek.
  • git reflog: Git śledzi aktualizacje końcówek gałęzi za pomocą mechanizmu zwanego dziennikami referencyjnymi lub „reflogami”. Reflogs śledzi, kiedy odniesienia Git zostały zaktualizowane w lokalnym repozytorium. Oprócz reflogów końcówek gałęzi, utrzymywany jest specjalny reflog dla skrytki Gita. Reflogi są przechowywane w katalogach w katalogu lokalnego repozytorium .git. Katalogi git reflog można znaleźć pod adresem .git/logs/refs/heads/., .git/logs/HEADa także, .git/logs/refs/stashjeśli w repozytorium użyto skrytki git. git reflog na wysokim poziomie na Rewriting Historystronie.
    git reflog expire --expire=now --expire-unreachable=now --all
    Oprócz zachowywania historii w reflogu, Git ma wewnętrzne daty wygaśnięcia, kiedy będzie przycinał odłączone zatwierdzenia. Ponownie, są to wszystkie szczegóły implementacji, które git gcobsługują i git prunenie powinny być używane samodzielnie.
  • git gc --aggressive: git-gc - wyczyść niepotrzebne pliki i zoptymalizuj lokalne repozytorium.
    W tle git gc faktycznie wykonuje pakiet innych wewnętrznych komend, takich jak git prune, git repack, git pack and git rerere. Głównym obowiązkiem tych komend jest zidentyfikowanie wszystkich obiektów Git, które są poza poziomami progowymi ustawionymi w git gckonfiguracji. Po zidentyfikowaniu obiekty te są następnie kompresowane lub odpowiednio przycinane.

Zwykłe z wynikiem:

$ git remote prune origin && git repack && git prune-packed && git reflog expire --expire=1.month.ago && git gc --aggressive
Enumerating objects: 535, done.
Counting objects: 100% (340/340), done.
Delta compression using up to 2 threads
Compressing objects: 100% (263/263), done.
Writing objects: 100% (340/340), done.
Total 340 (delta 104), reused 0 (delta 0)
Enumerating objects: 904, done.
Counting objects: 100% (904/904), done.
Delta compression using up to 2 threads
Compressing objects: 100% (771/771), done.
Writing objects: 100% (904/904), done.
Total 904 (delta 343), reused 561 (delta 0)
Yash
źródło