Jak usunąć plik z historii Git?

91

Jakiś czas temu dodałem informacje (pliki), które muszą być prywatne. Usunięcie z projektu nie jest problemem, ale muszę też usunąć go z githistorii.

Używam Git i Github (konto prywatne).

Uwaga: W tym wątku jest coś podobnego, ale tutaj jest stary plik, który został dodany do gałęzi funkcji, ta gałąź została połączona z gałęzią rozwojową i ostatecznie połączona z główną, ponieważ wprowadzono wiele zmian. Więc to nie to samo i potrzebna jest zmiana historii i ukrycie tych plików dla zachowania prywatności.

Marcos R. Guevara
źródło
3
Musiałbyś napisać od nowa historię. Na przykład git rebasewtedygit push -f
Cory Kramer
filter-branchMetoda opisana w sugerowanej duplikatu będzie robić to, co chcesz.
1615903
Również stackoverflow.com/a/17890278, który wskazuje na BFG, który może być szybszy niż używaniegit filter-branch
Hasturkun
ale po prostu idź szybciej i zrób to samo i muszę używać javy, czytam @Hasturkun
Marcos R. Guevara

Odpowiedzi:

115

Znalazłem tę odpowiedź i pomogło:

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD

Znalazłem go tutaj https://myopswork.com/how-remove-files-completely-from-git-repository-history-47ed3e0c4c35

Petro Franko
źródło
5
Ostrzeżenie: tworzy to mnóstwo zatwierdzeń i powoduje rozbieżności. Prawdopodobnie będziesz musiał zmuszać do pchnięcia, ale byłem zbyt przerażony.
sudo
1
Oddanie tego, co powiedział @sudo, ale zadziałało w moim nowym oddziale, do którego przypadkowo się zobowiązałem .env. Szybkie i rzeczowe rozwiązanie.
Joe Scotto,
1
Rzeczywiście, proste naciśnięcie siły działa! Też się bałem, ale wszystko popierałem.
wutBruh
1
Możesz także określić zakres zatwierdzeń jako ostatni argument. Jeśli dane zatwierdzenie było niedawne, zrób <previous_hash>..HEADi zaoszczędź trochę czasu.
Victor Sergienko
po tym działa tylko u mniegit push --force
Sebastian Schmal
49

Jeśli niedawno zatwierdziłeś ten plik lub jeśli plik ten zmienił się w jednym lub dwóch zatwierdzeniach, to sugerowałbym użycie rebasei cherrypickusunięcie tego konkretnego zatwierdzenia.

W przeciwnym razie musiałbyś przepisać całą historię.

git filter-branch --tree-filter 'rm -f <path_to_file>' HEAD

Kiedy jesteś zadowolony ze zmian i upewniłeś się, że wszystko wydaje się w porządku, musisz zaktualizować wszystkie zdalne oddziały -

git push origin --force --all

Uwaga: - To złożona operacja i musisz być świadomy tego, co robisz. Najpierw spróbuj zrobić to w repozytorium demonstracyjnym, aby zobaczyć, jak to działa. Musisz również poinformować o tym innych programistów, aby w międzyczasie nie wprowadzali żadnych zmian.

hspandher
źródło
po przepisaniu całej historii, aby zachować zmiany w repozytorium (github), co należy zrobić?
Marcos R. Guevara
dziękuję, poczekam na zrobienie tego i spróbuję z repozytorium demonstracyjnym, zaktualizuję wszystko, co zostało zrobione tutaj.
Marcos R. Guevara
Przez pomyłkę zapomniałem dodać --all. Teraz mówi, że wszystko jest aktualne za każdym razem, gdy ponownie uruchomię push z oboma argumentami. Plik nie jest usuwany z innych gałęzi. Co mam teraz zrobić?
Reeshabh Ranjan
Dlaczego w twojej sugestii jest --tree-filterraczej użycie , niż --index-filterodpowiedź @ PetroFranko?
einpoklum
14
  • usuń plik i przepisz historię z zatwierdzenia wykonanego z usuniętym plikiem (spowoduje to utworzenie nowego skrótu zatwierdzenia z zatwierdzonego pliku):

    git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA' --prune-empty --tag-name-filter cat -- --all

  • teraz wymuś repozytorium:

    git push origin --force --all

  • teraz powiedz swoim współpracownikom rebase.

suhailvs
źródło
7

Użycie pakietu bfg repo-cleaner jest kolejną realną alternatywą dla git-filter-branch. Podobno jest też szybszy ...

c1au61o_HH
źródło
7
  • Przede wszystkim dodaj go do swojego .gitignorepliku i nie zapomnij zatwierdzić pliku :-)
  • Możesz użyć tej strony: http://gtiignore.io, aby wygenerować .gitignoredla siebie i dodać wymaganą ścieżkę do swoich plików binarnych / folderów

  • Po dodaniu pliku do .gitignoreprogramu BFG można usunąć „stary” plik binarny.


How to remove big files from the repository

Możesz użyć git filter-branchlub BFG. https://rtyley.github.io/bfg-repo-cleaner/

BFG Repo-Cleaner

alternatywa dla git-filter-branch.

BFG jest prostszą i szybszą alternatywą dla gałęzi git-filter do czyszczenia złych danych z historii repozytorium Git:

* Usuwanie szalonych dużych plików *
* Usuwanie haseł, danych logowania i innych prywatnych danych

Przykłady (z oficjalnej strony)

We wszystkich tych przykładach bfg jest aliasem dla java -jar bfg.jar.

# Delete all files named 'id_rsa' or 'id_dsa' :
bfg --delete-files id_{dsa,rsa}  my-repo.git

wprowadź opis obrazu tutaj

CodeWizard
źródło
6

Przeczytałem ten artykuł na GitHubie , który doprowadził mnie do następującego polecenia (podobnego do zaakceptowanej odpowiedzi, ale nieco solidniejszego):

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --prune-empty --tag-name-filter cat -- --all
Vancy-spodnie
źródło
4

git-repo-filter

gitzaleca użycie git-filter-repo (gdy git filter-branchpolecenie jest wykonywane). Istnieje długa lista powodów, dla których jest lepsza niż jakiekolwiek inne alternatywy ( https://github.com/newren/git-filter-repo#why-filter-repo-instead-of-other-alternatives ), moje doświadczenie jest takie to jest bardzo proste i bardzo szybkie.

To polecenie usuwa plik ze wszystkich zatwierdzeń we wszystkich gałęziach:

git filter-repo --path <path to the file or directory> --invert-paths

Można określić wiele ścieżek, używając wielu --pathparametrów. Szczegółową dokumentację można znaleźć tutaj: https://www.mankier.com/1/git-filter-repo

Tibor Takács
źródło