Jak mogę wyczyścić folder .git? Wyczyściłem katalog mojego projektu, ale .git nadal jest ogromny

86

Plik .git / objects w moim katalogu projektu rails jest nadal ogromny, po usunięciu setek megabajtów przypadkowo wygenerowanych śmieci.

Próbowałem git add -A, podobnie jak inne polecenia, zaktualizować indeks i usunąć nieistniejące pliki. Wychodzę, być może niepoprawnie, że pliki z dwoma nazwami znaków w katalogu to bloby. Próbowałem wrócić do poprzednich zatwierdzeń, ale bez powodzenia.

Co mogę zrobić, aby wyczyścić ten katalog?

żarówki 24
źródło

Odpowiedzi:

138
  • Jeśli dodałeś pliki, a następnie je usunąłeś, obiekty blob nadal istnieją, ale wiszą. git fsckwyświetli nieosiągalne obiekty blob i git pruneusunie je.

  • Jeśli dodałeś pliki, zatwierdziłeś je, a następnie wycofałeś git reset --hard HEAD^, utknęły one trochę głębiej. git fscknie wyświetli żadnych wiszących commits ani blobów, ponieważ reflog twojej gałęzi trzyma je. Oto jeden sposób na zapewnienie, że pozostaną tylko obiekty, które są w twojej historii:

    git reflog expire --expire=now --all
    git repack -ad  # Remove dangling objects from packfiles
    git prune       # Remove dangling loose objects
    
  • Innym sposobem jest również sklonowanie repozytorium, ponieważ będzie ono zawierało tylko te obiekty, które są osiągalne. Jeśli jednak wiszące obiekty zostały spakowane (i jeśli wykonałeś wiele operacji, git mógł spakować się automatycznie), wtedy lokalny klon będzie nosił cały plik pakietu:

    git clone foo bar                 # bad
    git clone --no-hardlinks foo bar  # also bad
    

    Musisz określić protokół, aby wymusić na git obliczenie nowej paczki:

    git clone file://foo bar  # good
    
Josh Lee
źródło
Tak, popełniłem, zanim zauważyłem problem. Próbowałem wszystkiego oprócz ostatniego polecenia. Kiedy uruchamiam to z katalogu mojego projektu „ostrzeżenie: Wygląda na to, że sklonowałeś puste repozytorium”. Czytałem dokumentację, ale to ciężki materiał. Jak mogę wskazać klon na właściwe źródło?
żarówki 24
1
@user file://fooAdres URL jest względny w stosunku do bieżącego katalogu, a file:///home/me/foo(trzy ukośniki) jest bezwzględne.
Josh Lee
dzięki! to jest zmniejszone o połowę, ale moje opakowanie jest nadal dziesięć razy większe niż reszta repozytorium. Próbowałem przycinać ...
żarówki 24
1
@user Jeśli wiele zatwierdzeń błędnie zawiera duże pliki, możesz chcieć użyć git-filter-branch do ich wybrania.
Josh Lee,
2
Przepraszamy, bez skutku. Mój kierownik ds. Rozwoju mówi, że rozmiar mieści się teraz w dopuszczalnym, ale niekorzystnym zakresie. Jeśli masz czas, by dalej karmić mnie łyżeczką, byłoby świetnie, ale postawiłaś mnie na nogi. Dzięki jleedev.
żarówki 24
34

Czy wypróbowałeś git gcpolecenie?

ryanprayogo
źródło
3
git gc --aggressive --prunepracuje dla mnie. git gcnie. Może domyślne ustawienie nie wystarczy.
Moonlight Knight
14

Sparkleshare utworzył 13 GB plików tmp_pack_ w moim git po niepowodzeniu wielokrotnego pobierania dużych obrazów. Jedyne, co pomogło, to ...

rm -f .git/objects/*/tmp_*

„git gc” nie usunął tych plików.

kot
źródło
To dość brutalne rozwiązanie, ale nie widzę powodu, dla którego to nie zadziała. Ładny!
żarówek24
1
Desperackie sytuacje wymagają desperackich środków, zadziałało jak urok! Tks.
medina
rm jest dla polecenia linux? a co z użytkownikiem systemu Windows, a następnie @cat?
gumuruh
7

Jeśli nadal masz duże repozytorium po przycięciu i przepakowaniu ( gc --aggressive --prune=tomorrow...), możesz po prostu poszukać nieparzystego:

git rev-list --objects --all |
    while read sha1 fname
    do 
        echo -e "$(git cat-file -s $sha1)\t$\t$fname"
    done | sort -n

To da ci posortowaną listę obiektów w rosnącym rozmiarze. Możesz użyć git-filter-branch, aby usunąć winowajcę z repozytorium.

Wskazówki można znaleźć w sekcji „Usuwanie obiektów” w http://progit.org/book/ch9-7.html

sehe
źródło
@DavidJames dzięki za podpowiedź. Zrobiłem to jeszcze bardziej czytelny, IMO
sehe
Na wypadek gdyby ktoś się o to potknął: w argumentach w nawiasach jest literówka: powinno być --aggressive. Próbowałem edytować, ale okazuje się, że nie możesz edytować tak małej literówki.
hellobenallan
@hellobenallan podziękowania dla notatki, stałe
sehe
1

Rekurencyjnie:

find ./ -iname '*.!*' -size 0 -delete
for i in */.git; do ( echo $i; cd $i/..; git gc --aggressive --prune=now --force; ); done
Marcelo Grebois
źródło