filename.orig
Kilka przypadków temu przypadkowo przesłałem niechciany plik ( podczas rozwiązywania scalenia) do mojego repozytorium, do tej pory tego nie zauważając. Chcę całkowicie usunąć plik z historii repozytorium.
Czy możliwe jest przepisanie historii zmian tak, aby filename.orig
nigdy nie była dodawana do repozytorium?
git
git-filter-branch
git-rewrite-history
git-rm
Grant Limberg
źródło
źródło
Odpowiedzi:
Nie używaj tego przepisu, jeśli Twoja sytuacja nie jest zgodna z opisem w pytaniu. Ten przepis służy do naprawiania złego scalenia i odtwarzania dobrych zatwierdzeń na ustalonym scaleniu.
Chociaż
filter-branch
zrobi to, co chcesz, jest to dość złożone polecenie i prawdopodobnie wybrałbym togit rebase
. To prawdopodobnie osobiste preferencje.filter-branch
można to zrobić za pomocą pojedynczej, nieco bardziej złożonej komendy, podczas gdyrebase
rozwiązanie wykonuje równoważne operacje logiczne krok po kroku.Wypróbuj następujący przepis:
(Zauważ, że tak naprawdę nie potrzebujesz gałęzi tymczasowej, możesz to zrobić za pomocą „odłączonej HEAD”, ale musisz zanotować identyfikator zatwierdzenia wygenerowany przez
git commit --amend
krok w celu dostarczenia dogit rebase
polecenia zamiast używania gałęzi tymczasowej imię.)źródło
git rebase -i
byłoby szybciej i tak łatwo? $ git rebase -i <sh1-of-merge> Oznacz prawidłowy jako „edytuj” $ git rm somefile.orig $ git commit --amend $ git rebase - continue Jednak z jakiegoś powodu wciąż mam ten plik gdzieś ostatni czas to zrobiłem. Prawdopodobnie czegoś brakuje.git rebase -i
jest bardzo przydatny, szczególnie gdy masz do wykonania wiele operacji rebase-y, ale dobrze jest dokładnie opisać, kiedy tak naprawdę nie wskazujesz komuś ramienia i widzisz, co robi z jego edytorem. Używam vima, ale nie wszyscy byliby zadowoleni z: „ggjcesquash <Esc> jddjp: wq” i instrukcji takich jak „Przenieś górną linię na bieżącą drugą linię i zmień pierwsze słowo w czwartej linii na„ edytuj ”teraz zapisz i quit ”szybko wydają się bardziej skomplikowane niż w rzeczywistości. Zazwyczaj kończy się z niektórymi--amend
i--continue
działań, jak również.Wprowadzenie: masz 5 dostępnych rozwiązań
Oryginalny plakat stwierdza:
Istnieje wiele różnych sposobów całkowitego usunięcia historii pliku z git:
W przypadku oryginalnego plakatu, zmiana zatwierdzenia nie jest tak naprawdę opcją samą w sobie, ponieważ później dokonał kilku dodatkowych zatwierdzeń, ale dla kompletności wyjaśnię również, jak to zrobić, dla każdego, kto tylko chce zmienić poprzednie zatwierdzenie.
Zauważ, że wszystkie te rozwiązania wymagają zmiany / ponownego zapisywania historii / zatwierdzeń w inny sposób, więc każdy, kto ma stare kopie zatwierdzeń, będzie musiał wykonać dodatkową pracę, aby ponownie zsynchronizować swoją historię z nową historią.
Rozwiązanie 1: Zobowiązania korygujące
Jeśli przypadkowo dokonałeś zmiany (np. Dodając plik) w poprzednim zatwierdzeniu i nie chcesz, aby historia tej zmiany już istniała, możesz po prostu zmienić poprzednie zatwierdzenie, aby usunąć z niego plik:
Rozwiązanie 2: Twardy reset (prawdopodobnie plus rease)
Podobnie jak w rozwiązaniu nr 1, jeśli chcesz po prostu pozbyć się poprzedniego zatwierdzenia, masz również opcję twardego resetu do jego rodzica:
Że komenda będzie trudno zresetować oddziału do poprzedniego 1 st rodzica popełnił.
Jeśli jednak , podobnie jak oryginalny plakat, dokonałeś kilku zatwierdzeń po zatwierdzeniu, w którym chcesz cofnąć zmianę, nadal możesz użyć twardego resetu, aby ją zmodyfikować, ale to również wymaga użycia bazy. Oto kroki, których możesz użyć, aby zmienić zatwierdzenie dalej w historii:
Rozwiązanie 3: Nieinteraktywne Rebase
Działa to, jeśli chcesz całkowicie usunąć zatwierdzenie z historii:
Rozwiązanie 4: Interaktywne zmiany
To rozwiązanie pozwoli ci osiągnąć te same rzeczy, co rozwiązania 2 i 3, tj. Zmodyfikować lub usunąć zatwierdzenia z powrotem w historii niż poprzednie wcześniejsze zatwierdzenie, więc to, które rozwiązanie wybierzesz, zależy od ciebie. Interaktywne rebazy nie nadają się do rebasingu setek commits ze względu na wydajność, dlatego w takich sytuacjach użyłbym nieinteraktywnych rebase'ów lub rozwiązania gałęzi filtrowania (patrz poniżej).
Aby rozpocząć interaktywną bazę, użyj następujących poleceń:
Spowoduje to, że git przewinie historię zatwierdzeń z powrotem do elementu nadrzędnego zatwierdzenia, które chcesz zmodyfikować lub usunąć. Następnie wyświetli listę zatwierdzonych przewinięć w odwrotnej kolejności w dowolnym ustawionym git edytorze (domyślnie jest to Vim):
Zatwierdzenie, które chcesz zmodyfikować lub usunąć, będzie na górze tej listy. Aby go usunąć, po prostu usuń jego linię z listy. W przeciwnym wypadku, należy wymienić „pick” z „edit” na 1 st linii, tak jak poniżej:
Następnie wprowadź
git rebase --continue
. Jeśli zdecydujesz się całkowicie usunąć zatwierdzenie, to wszystko, co musisz zrobić (oprócz weryfikacji, zobacz ostatni krok tego rozwiązania). Jeśli z drugiej strony chcesz zmodyfikować zatwierdzenie, git ponownie zastosuje zatwierdzenie, a następnie zatrzyma zmianę bazy.W tym momencie możesz usunąć plik i zmienić zatwierdzenie, a następnie kontynuować rebase:
Otóż to. Na koniec, niezależnie od tego, czy zmodyfikowałeś zatwierdzenie, czy całkowicie go usunąłeś, zawsze dobrym pomysłem jest sprawdzenie, czy nie dokonano żadnych innych nieoczekiwanych zmian w twojej gałęzi, różnicując go swoim stanem przed zmianą bazy:
Rozwiązanie 5: Filtrowanie oddziałów
Wreszcie, to rozwiązanie jest najlepsze, jeśli chcesz całkowicie usunąć wszystkie ślady istnienia pliku z historii, a żadne z pozostałych rozwiązań nie spełnia tego zadania.
To usunie
<file>
wszystkie zatwierdzenia, poczynając od głównego zatwierdzenia. Jeśli zamiast tego chcesz po prostu przepisać zakres zatwierdzeniaHEAD~5..HEAD
, możesz przekazać to jako dodatkowy argumentfilter-branch
, jak wskazano w tej odpowiedzi :Ponownie, po
filter-branch
zakończeniu, zwykle dobrym pomysłem jest sprawdzenie, czy nie ma innych nieoczekiwanych zmian, poprzez różnicowanie gałęzi do poprzedniego stanu przed operacją filtrowania:Alternatywa dla rozgałęzień: BFG Repo Cleaner
Słyszałem, że narzędzie BFG Repo Cleaner działa szybciej niż
git filter-branch
, więc możesz również sprawdzić to jako opcję. Jest nawet oficjalnie wspomniany w dokumentacji gałęzi filtrów jako realna alternatywa:Dodatkowe zasoby
źródło
filter-branch
powoduje ponowne obliczanie skrótów? Jeśli zespół pracuje z repozytorium, w którym duży plik powinien być filtrowany, jak to zrobić, aby wszyscy mieli ten sam stan repo?Jeśli od tego czasu nic nie popełniłeś, po prostu
git rm
plik igit commit --amend
.Jeśli masz
przejdzie każdą zmianę od
merge-point
doHEAD
, usunie nazwę pliku.orig i przepisze zmianę. Użycie--ignore-unmatch
oznacza, że polecenie nie zawiedzie, jeśli z jakiegoś powodu brakuje pliku filename.orig w zmianie. Jest to zalecany sposób z sekcji Przykłady na stronie man git-filter-branch .Uwaga dla użytkowników systemu Windows: ścieżka do pliku musi zawierać ukośniki
źródło
git-filter-branch
wydaje się dawać pierwszą.filter-branch
"
a nie'
podczas korzystania z systemu Windows, w przeciwnym razie pojawi się niepoprawnie sformułowany błąd „zła wersja”.To najlepszy sposób:
http://github.com/guides/completely-remove-a-file-from-all-revisions
Pamiętaj tylko, aby najpierw wykonać kopię zapasową plików.
EDYTOWAĆ
Edycja Neon została niestety odrzucona podczas przeglądu.
Zobacz post Neons poniżej, może zawierać przydatne informacje!
Np. Aby usunąć wszystkie
*.gz
pliki przypadkowo przypisane do repozytorium git:To wciąż nie działało dla mnie? (Obecnie jestem w wersji git 1.7.6.1)
Nie jestem pewien, dlaczego, ponieważ miałem tylko JEDNĄ gałąź master. Tak czy inaczej, w końcu naprawdę wyczyściłem moje repozytorium git, pchając do nowego pustego repozytorium git, np.
(tak!)
Następnie sklonowałem to do nowego katalogu i przeniosłem do niego folder .git. na przykład
(tak! w końcu posprzątał!)
Po sprawdzeniu, że wszystko jest w porządku, możesz usunąć katalogi
../large_dot_git
i../tmpdir
(może za kilka tygodni lub miesięcy, na wszelki wypadek ...)źródło
--prune-empty
do polecenia filter-branch.Przepisywanie historii Git wymaga zmiany wszystkich identyfikatorów zatwierdzeń, których dotyczy ten problem, więc każdy, kto pracuje nad projektem, będzie musiał usunąć swoje stare kopie repozytorium i wykonać nowy klon po wyczyszczeniu historii. Im więcej ludzi to niedogodności, tym bardziej trzeba mieć dobry powód, by to zrobić - zbędny plik nie jest tak naprawdę przyczyną problemu, ale jeśli tylko ty pracujesz nad projektem, równie dobrze można oczyścić historię Git jeśli chcesz do!
Aby było to tak proste, jak to możliwe, polecam użycie BFG Repo-Cleaner , prostszej, szybszej alternatywy dla
git-filter-branch
specjalnie zaprojektowanej do usuwania plików z historii Git. Jednym ze sposobów, w jaki ułatwia ci to życie, jest fakt, że domyślnie obsługuje wszystkie referencje (wszystkie tagi, gałęzie itp.), Ale jest także 10 - 50 razy szybszy.Powinieneś uważnie wykonać następujące kroki: http://rtyley.github.com/bfg-repo-cleaner/#usage - ale rdzeń jest po prostu następujący: pobierz słoik BFG (wymaga Java 6 lub nowszej) i uruchom to polecenie :
Cała historia repozytorium zostanie przeskanowana, a każdy plik o nazwie
filename.orig
(nieobecny w ostatnim zatwierdzeniu ) zostanie usunięty. Jest to znacznie łatwiejsze niż używaniegit-filter-branch
tej samej rzeczy!Pełne ujawnienie: jestem autorem BFG Repo-Cleaner.
źródło
źródło
Aby dodać to do rozwiązania Charlesa Baileya, użyłem git rebase -i do usunięcia niechcianych plików z wcześniejszego zatwierdzenia i działało to jak urok. Kroki:
źródło
Najprostszy sposób, jaki znalazłem, został zasugerowany przez
leontalbot
(jako komentarz), który jest postem opublikowanym przez Anoopjohna . Myślę, że jest to warte własnej przestrzeni jako odpowiedź:(Przekształciłem go w skrypt bash)
Wszystkie kredyty trafiają do
Annopjohn
ileontalbot
za wskazanie tego.UWAGA
Pamiętaj, że skrypt nie obejmuje sprawdzania poprawności, więc upewnij się, że nie popełniasz błędów i że masz kopię zapasową na wypadek, gdyby coś poszło nie tak. To działało dla mnie, ale może nie działać w twojej sytuacji. KORZYSTAJ Z niego OSTROŻNIE (kliknij link, jeśli chcesz wiedzieć, co się dzieje).
źródło
Zdecydowanie
git filter-branch
jest to najlepsza droga.Niestety, nie wystarczy to całkowicie usunąć
filename.orig
z repozytorium, ponieważ nadal można do nich odwoływać się za pomocą tagów, wpisów na blogu, pilotów itp.Polecam również usunięcie wszystkich tych referencji, a następnie wywołanie modułu wyrzucania elementów bezużytecznych. Możesz użyć
git forget-blob
skryptu z tej witryny, aby zrobić to wszystko w jednym kroku.git forget-blob filename.orig
źródło
Jeśli to ostatni zatwierdzenie, które chcesz wyczyścić, próbowałem z git w wersji 2.14.3 (Apple Git-98):
źródło
git reflog expire --expire=now --all; git gc --prune=now
to bardzo zła rzecz do zrobienia. O ile nie zabraknie ci miejsca na dysku, pozwól git śmieciowi zebrać te zatwierdzenia po kilku tygodniachDo tego
git filter-branch
został zaprojektowany.źródło
Możesz także użyć:
git reset HEAD file/path
źródło