Git: Jak usunąć plik ze zmian historycznych?


113

Mam zatwierdzenie z identyfikatorem 56f06019 (na przykład). W tym zatwierdzeniu przypadkowo zatwierdziłem duży plik (50 MB). W innym zatwierdzeniu dodaję ten sam plik, ale w odpowiednim rozmiarze (mały). Teraz moje repozytorium, gdy klonuję, jest zbyt ciężkie :( Jak usunąć ten duży plik z historii repozytorium, aby zmniejszyć rozmiar mojego repozytorium?


w moim przypadku nie jest to duży plik, ale plik konfiguracyjny zawierający kredyty bazy danych. Uczyłem się gita, w tamtym czasie nie wiedziałem o .gitignore.
— Rashi


Odpowiedzi:


165

Rozdział 9 książki Pro Git zawiera sekcję dotyczącą usuwania obiektów .

Przedstawię tutaj pokrótce kroki:

git filter-branch --index-filter \
    'git rm --cached --ignore-unmatch path/to/mylarge_50mb_file' \
    --tag-name-filter cat -- --all

Podobnie jak opisana wcześniej opcja zmiany bazy, filter-branchjest operacją przepisywania. Jeśli opublikowałeś historię, będziesz musiał --forcenaciskać na nowe referencje.

filter-branchPodejście jest znacznie mocniejszy niż rebasepodejście, ponieważ

  • umożliwia jednoczesną pracę na wszystkich gałęziach / referencjach,
  • zmienia nazwy wszystkich tagów w locie
  • działa bezproblemowo, nawet jeśli od dodania pliku było kilka zatwierdzeń scalających
  • działa poprawnie, nawet jeśli plik był (ponownie) dodawany / usuwany kilka razy w historii (a) gałęzi (-ów)
  • nie tworzy nowych, niepowiązanych zatwierdzeń, ale raczej kopiuje je podczas modyfikowania drzew z nimi powiązanych. Oznacza to, że takie rzeczy jak podpisane zatwierdzenia, notatki do zmian itp. Są zachowane

filter-branch przechowuje również kopie zapasowe, więc rozmiar repozytorium nie zmniejszy się natychmiast, chyba że wygaśniesz reflogs i garbage collect:

rm -Rf .git/refs/original       # careful
git gc --aggressive --prune=now # danger

1
Warto zauważyć, że to nie działa pod Windows cmd.exe. Wydaje się jednak działać dobrze pod cygwinem.
— Fałszywe nazwisko

2
Mam powyższą gałąź filtra git do pracy przy użyciu podwójnych cudzysłowów zamiast pojedynczych cudzysłowów (w systemie Windows Server 2012 cmd.exe)
— JCii,

1
To, co zadziałało, to ta linia poleceń filter-branch. git filter-branch --force --index-filter 'git rm --ignore-unmatch --cached PathTo/MyFile/ToRemove.dll' -- fbf28b005^.. Wtedy rm --recursive --force .git/refs/originali rm --recursive --force .git/logs wtedy użyłem git prune --expire now i git gc --aggressive To działało lepiej dla mnie niż twoje dokładne kroki wymienione powyżej. Dziękujemy za dołączenie linku do książki Git Pro, ponieważ była ona bezcenna.
— dacke.geo

Po poleceniu filter-branch jedynym sposobem, w jaki mogłem zmniejszyć rozmiar folderu .git, było wykonanie polecenia znalezionego tutaj: stackoverflow.com/questions/1904860/ ... git -c gc.reflogExpire = 0 -c gc. reflogExpireUnreachable = 0 -c gc.rerereresolved = 0 \ -c gc.rerereunresolved = 0 -c gc.pruneExpire = teraz gc "$ @"
— Steve Ardis

Aby zmniejszyć repozytorium, użyłem poleceń wymienionych w dokumencie git filter-branch: git-scm.com/docs/…
— Ludovic Ronsin


0

Będziesz musiał skorzystać z git rebase w trybie interaktywnym. Przykład tutaj: Jak mogę usunąć zatwierdzenie na GitHubie? i jak usunąć stare zmiany .

Jeśli twój commit jest na HEAD minus 10 commits:

$ git rebase -i HEAD~10

Po edycji twojej historii, musisz wcisnąć "nową" historię, musisz dodać +to force (zobacz refspec w opcjach push ):

$ git push origin +master

Jeśli inne osoby sklonowały już Twoje repozytorium, poinformujesz ich o tym, ponieważ właśnie zmieniłeś historię.


3
To nie usuwa dużego pliku z historii. Ponadto kanoniczny sposób wymuszenia pchnięcia to git push --forcelub git push -f(co nie wymaga od ludzi znajomości celu wypychania gałęzi)
— sehe

Opierając się na pytaniu, nowy plik jest dokładnie taki sam jak stary plik, czyli ta sama ścieżka. Dlatego nie możesz bezpośrednio używać git rmna ścieżce.
— Loïc d'Anterroches

2
@sehe, jeśli wykonasz rebase eliminując zatwierdzenie z ogromnym plikiem, to zniknie na dobre.
— vonbrand

@vonbrand tylko z tej gałęzi, w której została zmieniona. Nie zakładam, że gałąź „from” zostanie usunięta. Ale tak, jeśli usuniesz gałąź drzewa wersji, pomoże to: _
— sehe

@sehe, oczywiście, musisz ścigać wszystkie gałęzie zawierające naruszające zatwierdzenie. Jeśli jest przed jakimś krzakiem w repozytorium, będziesz musiał dużo przeorganizować. Ale rebase jest do tego narzędziem.
— vonbrand

0

Próbowałem użyć następującej odpowiedzi w systemie Windows https://stackoverflow.com/a/8741530/8461756

Pojedynczy cudzysłów nie działa w systemie Windows, potrzebujesz podwójnych cudzysłowów.

Następujące pracowały dla mnie.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathRelativeRepositoryRoot / bigfile.csv" - --all

Po usunięciu dużego pliku mogłem przesłać moje zmiany do mastera github.


0

Możesz użyć prostego polecenia, aby usunąć

 git rm -r -f app/unused.txt 
 git rm -r -f yourfilepath
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.