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.