Usuń pliki z Git commit


1612

Korzystam z Git i wykorzystałem kilka plików

git commit -a

Później odkryłem, że plik został błędnie dodany do zatwierdzenia.

Jak mogę usunąć plik z ostatniego zatwierdzenia?


2
Ten link jest idealny do twojego pytania: stackoverflow.com/questions/307828/…
b3h3m0th

@CharlesB: tak, to moje ostatnie zatwierdzenie
Lolly

8
czy wypchnąłeś zatwierdzenie na serwer?
Paritosh Singh,

4
Po prostu robię to, używając:git reset filepath
felipekm

Odpowiedzi:


3087

Myślę, że inne odpowiedzi tutaj są błędne, ponieważ jest to kwestia przeniesienia błędnie zatwierdzonych plików z powrotem do obszaru testowego z poprzedniego zatwierdzenia, bez anulowania wprowadzonych do nich zmian. Można to zrobić tak, jak sugerował Paritosh Singh:

git reset --soft HEAD^ 

lub

git reset --soft HEAD~1

Następnie zresetuj niechciane pliki, aby wykluczyć je z zatwierdzenia:

git reset HEAD path/to/unwanted_file

Teraz zatwierdzaj ponownie, możesz nawet ponownie użyć tego samego komunikatu zatwierdzenia:

git commit -c ORIG_HEAD  

86
Dzięki za to. Warto dodać, że jeśli już wypchnąłeś swoje wcześniejsze (złe) zatwierdzenie, a teraz próbujesz git pushnaprawić swoją repo, będzie narzekać Updates were rejected because the tip of your current branch is behind its remote counterpart.. Jeśli masz pewność, że chcesz je popchnąć (np. To twój widelec), możesz skorzystać z -fopcji wymuszenia pchnięcia, np git push origin master -f. (Nie rób tego z repozytorium nadrzędnym, z którego inni się
ściągają

57
git reset --soft HEAD^to moja najczęstsza operacja cofania
funroll

2
@PabloFernandez, po pierwsze, zaakceptowaną odpowiedzią mogło być to, czego szukał PO (również zostało opublikowane kilka miesięcy wcześniej). Po drugie, zaakceptowane odpowiedzi są zawsze na wierzchu, niezależnie od liczby głosów.
MITjanitor,

4
@PabloFernandez u góry wszystkich odpowiedzi to trzy zakładki, które pozwalają kontrolować kolejność odpowiedzi: aktywne , najstarsze i głosy . Domyślam się, że twój jest ustawiony na najstarszy . Przełącz go na głosy, mimo że zaakceptowana odpowiedź będzie nadal na górze, ta odpowiedź będzie druga.
ahsteele

15
Wiedziałem o tym tyle, git resetale chciałem wpłynąć na istniejące zatwierdzenie „na miejscu”. Właśnie się dowiedziałem git commit -C. Więc dla mnie to, czego chcę, to twoja dokładna recepta z jeszcze jednym krokiem, „nowe zatwierdzenie ponownie” zapisane jako git commit -C [hash of original HEAD commit from first step].
metamatt

323

UWAGA ! Jeśli chcesz tylko usunąć plik z poprzedniego zatwierdzenia i zachować go na dysku , przeczytaj odpowiedź juzzlin tuż powyżej.

Jeśli jest to twój ostatni zatwierdzenie i chcesz całkowicie usunąć plik z lokalnego i zdalnego repozytorium , możesz:

  1. usuń plik git rm <file>
  2. zatwierdzić z poprawką flagi: git commit --amend

Flaga zmiany nakazuje gitowi ponowne zatwierdzenie, ale „scal” (nie w sensie łączenia dwóch gałęzi) to zatwierdzenie z ostatnim zatwierdzeniem.

Jak stwierdzono w komentarzach, użycie git rmtutaj jest jak użycie samego rmpolecenia!


120
możesz także użyć git rm --cacheddo przechowywania plików na dysku
Arkadiy Kukarkin

14
Ostrzeżenie dla osób przeglądających tę odpowiedź: upewnij się, że chcesz USUNĄĆ plik (jak już go nie ma!), A nie tylko usunąć go z listy zatwierdzeń.
Scott Biggs

8
Aby dodać do tego, co mówią inni (i łatwiej nie pamiętać, aby to zrobić, chyba że naprawdę chcesz): w poleceniu jest robić to, co sama robi! rmgitrm
jo

@CharlesB Czy możesz dodać notatkę z komentarza Arkadiy Kukarkin do swojej odpowiedzi, aby zwiększyć jej widoczność?
mopo922,

2
Zauważ, że pliki można nadal przywrócić, w przypadku zmiany zdania, zatwierdzenie przedtem git commit --amendjest nadal dostępne i można je znaleźć na przykład za pomocą git reflog. Więc nie jest tak źle, jak sugerują inne komentarze.
Steohan,

165

Istniejące odpowiedzi mówią o usunięciu niechcianych plików z ostatniego zatwierdzenia.

Jeśli chcesz usunąć niechciane pliki ze starego zatwierdzenia (nawet wypchnięte) i nie chcesz tworzyć nowego zatwierdzenia, co jest niepotrzebne z powodu akcji:

1.

Znajdź zatwierdzenie, z którym ma być zgodny plik.

git checkout <commit_id> <path_to_file>

możesz to zrobić wiele razy, jeśli chcesz usunąć wiele plików.

2)

git commit -am "remove unwanted files"

3)

Znajdź commit_id zatwierdzenia, do którego pliki zostały błędnie dodane , powiedzmy tutaj „35c23c2”

git rebase 35c23c2~1 -i  // notice: "~1" is necessary

To polecenie otwiera edytor zgodnie z Twoimi ustawieniami. Domyślnym jest vim.

Przenieś ostatnie zatwierdzenie, które powinno być „usuń niechciane pliki”, do następnego wiersza niepoprawnego zatwierdzenia (w naszym przypadku „35c23c2”) i ustaw polecenie jako fixup:

pick 35c23c2 the first commit
fixup 0d78b28 remove unwanted files

Powinieneś być dobry po zapisaniu pliku.

Skończyć :

git push -f

Jeśli niestety występują konflikty, musisz je rozwiązać ręcznie.


2
Robienie tego z nano jest wspaniałe! Ctrl + K, Ctrl + U, wstaw „f”, Ctrl + X, wstaw „y” i voila!
sequielo

6
Jeśli chcesz usunąć pliki z repozytorium (nie systemu plików), zamiast po prostu przywrócić je do poprzedniej wersji, zamiast tego wykonaj krok 1 git rm --cached <file(s)>.
waldyrious

2
Poczekaj, możesz dowolnie przenosić zatwierdzenia wokół pliku bazy interaktywnej?
Dan Rosenstark

2
Całkowicie możesz, ale możesz (lub nie) mieć konflikty.
Brian

6
Proces ten można nieco ułatwić, dodając --fixup=35c23c2do git commitpolecenia. Spowoduje to automatyczne skonfigurowanie zatwierdzenia jako poprawki wymaganego zatwierdzenia, więc nie będziesz musiał określać go w bazie. Dodatkowo, jeśli dodasz --autosquashdo git rebasepolecenia, git automatycznie przeniesie zatwierdzenie do właściwej lokalizacji, więc nie musisz nic robić w interaktywnej bazie - po prostu zapisz wynik (co oznacza, że ​​nawet nie musisz -ioznaczać, mimo to lubię go używać, aby upewnić się, że wszystko wygląda tak, jak się spodziewam).
Guss

144

Jak wskazuje zaakceptowana odpowiedź, możesz to zrobić poprzez zresetowanie całego zatwierdzenia. Ale jest to dość ciężkie podejście.
Lepszym sposobem na to byłoby zachowanie zatwierdzenia i po prostu usunięcie z niego zmienionych plików.

git reset HEAD^ -- path/to/file
git commit --amend --no-edit

The git resetOdbędzie plik, jak to było w poprzednim commit, a etapie w indeksie. Plik w katalogu roboczym pozostaje nietknięty. Wtedy popełnić i zgnieść indeks do prądu popełnić.
git commit

To zasadniczo pobiera wersję pliku, która była w poprzednim zatwierdzeniu i dodaje ją do bieżącego zatwierdzenia. Powoduje to brak zmian sieci, a zatem plik jest skutecznie usuwany z zatwierdzenia.


5
Jest to o wiele lepsza odpowiedź na usunięcie tylko jednego pliku, bez przeglądu całego zatwierdzenia.
nimish

To jest dokładnie to samo, co ta odpowiedź: D stackoverflow.com/a/27340569/1623984
ThatsAMorais

@ThatsAMorais rzeczywiście :-). Zastanawiam się, czy to pytanie zostało połączone z innym, i dlatego go nie widziałem. A może jestem po prostu ślepy. W każdym razie myślę, że jestem skłonny pozostawić to, ponieważ oparte na głosach wydaje się być bardziej popularne (być może ludzie wolą krótką i bezpośrednią odpowiedź).
Patrick

Oczywiście, zostaw to! :) Wyraźnie mieliśmy dobry pomysł, a celem jest pomoc. Myślę, że łączenie jest dobrą teorią.
ThatsAMorais

Jak to zrobić, jeśli już pchnąłeś do oddziału na github? Po wykonaniu tej poprawki próbowałem wypchnąć i dostałem komunikat „Aktualizacje zostały odrzucone, ponieważ wskazówka twojego obecnego oddziału jest za wskazówką: jego zdalny odpowiednik”.
Ollie Williams

41

Jeśli nie opublikowałeś zmian na serwerze, możesz użyć

git reset --soft HEAD~1

Zresetuje wszystkie zmiany i powróci do jednego zatwierdzenia z powrotem

Jeśli wprowadziłeś zmiany, postępuj zgodnie z instrukcjami udzielonymi przez @CharlesB


2
-1 git reset usuwa zmiany nastąpiły plik z obszaru przejściowego, tutaj zmiana została zatwierdzona
CharlesB

OK, ale zachowam głos, ponieważ nie tego chce OP :) przepraszam
CharlesB

ok dla mnie jest w porządku, ale dlaczego przeciwnik tego nie chce. Jaki jest problem?
Paritosh Singh,

nie jest to wielka sprawa, ale ponieważ OP chce usunąć niechciany plik z ostatniego zatwierdzenia i po prostu resetuje się do stanu przed zatwierdzeniem. wciąż musisz powtórzyć zatwierdzenie.
CharlesB

3
@Aris użyj <git diff --cached>, aby zobaczyć zmiany
Paritosh Singh

37

Usunięcie pliku za pomocą rm spowoduje jego usunięcie!

Zawsze dodajesz do zatwierdzenia w git, zamiast go usuwać, więc w tym przypadku przywróć plik do stanu, w jakim znajdował się przed pierwszym zatwierdzeniem (może to być akcja usuwania „rm”, jeśli plik jest nowy), a następnie ponów zatwierdzenie, a plik pójdzie.

Aby przywrócić plik do poprzedniego stanu:

    git checkout <commit_id> <path_to_file>

lub aby przywrócić go do stanu na zdalnej GŁOWICY:

    git checkout origin/master <path_to_file>

następnie zmień zatwierdzenie i powinieneś zobaczyć, że plik zniknął z listy (i nie został usunięty z twojego dysku!)


36
git checkout HEAD~ path/to/file
git commit --amend

1
Jest to najlepszy sposób na modyfikację ostatniego zatwierdzenia, tego, który nie został wypchnięty. Spowoduje to zresetowanie zmian w jednym pliku, skutecznie usuwając ten plik z ostatniego zatwierdzenia.
Alex Bravo,

To także zmieniło plik. Jak zachować lokalne zmiany w pliku?
theonlygusti

29

Poniższa operacja usunie scenę tylko z zamierzonego pliku, o co poprosił OP.

git reset HEAD^ /path/to/file

Zobaczysz coś takiego ...

Zmiany do zatwierdzenia: (użyj „git reset HEAD ...”, aby wycofać się ze sceny)

zmodyfikowano: / path / to / file

Zmiany, które nie zostały wprowadzone dla zatwierdzenia: (użyj „git add ...”, aby zaktualizować, co zostanie zatwierdzone) (użyj „git checkout - ...”, aby odrzucić zmiany w katalogu roboczym)

zmodyfikowano: / path / to / file

  • „Zmiany do zatwierdzenia” to poprzednia wersja pliku przed zatwierdzeniem. Będzie to wyglądać jak usunięcie, jeśli plik nigdy nie istniał. Jeśli zatwierdzisz tę zmianę, nastąpi zmiana, która przywróci zmianę do pliku w oddziale.
  • „Zmiany, które nie zostały wprowadzone do zatwierdzenia” to zatwierdzona przez Ciebie zmiana i bieżący stan pliku

W tym momencie możesz zrobić, co chcesz z plikiem, na przykład zresetować do innej wersji.

Kiedy będziesz gotowy do zatwierdzenia:

git commit --amend -a

lub (jeśli wprowadzasz jakieś inne zmiany, których nie chcesz jeszcze zatwierdzać)

git commit add /path/to/file
git commit --amend

3
Odpowiedź juzzlina jest świetna, ale przesadne jest rozbrajanie całego zatwierdzenia, gdy tylko chcesz go zestrzelić. Odznaczenie całego zatwierdzenia może spowodować problemy, jeśli w tym zatwierdzeniu wprowadzono niestabilne zmiany w plikach, których nie chcesz utracić.
ThatsAMorais,

27

Wyjaśnię ci przykład.
Niech A, B, C będą 3 kolejnymi zatwierdzeniami. Zatwierdzenie B zawiera plik, który nie powinien był zostać zatwierdzony.

git log  # take A commit_id
git rebase -i "A_commit_ID" # do an interactive rebase
change commit to 'e' in rebase vim # means commit will be edited
git rm unwanted_file
git rebase --continue
git push --force-with-lease <branchName>    

Jeśli określony plik nie znajduje się w ostatnim lub poprzednim zatwierdzeniu, jest to najbardziej elegancki sposób. Powiedziałbym nawet, że jest to najbardziej elegancki sposób. Lubię interaktywne rebasing.
bvgheluwe

Dla pojedynczego zatwierdzenia zmień noopna edit [A_commit_ID]lube [A_commit_ID]
TamusJRoyce

23

Możesz po prostu spróbować.

git reset --soft HEAD~1

i utwórz nowy zatwierdzenie.

Istnieje jednak niesamowite oprogramowanie „gitkraken”. co ułatwia pracę z git.


1
I tylko pamiętaj: po tym będziesz musiał git commit --amendzaktualizować usunięcie pliku w swoim ostatnim zatwierdzeniu; a następnie możesz sprawdzić, czy rzeczywiście został usunięty za pomocągit log -1 --stat
sdbbs,

13
git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "removed unwanted file from git"

pozostawi ci nadal plik lokalny. Jeśli nie chcesz też pliku lokalnie, możesz pominąć opcję --cached.

Jeśli cała praca jest w twoim oddziale lokalnym, musisz zachować plik w późniejszym zatwierdzeniu, i podobnie jak w przypadku czystej historii, myślę, że prostszym sposobem może być:

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit --squash <commit_id>
git add <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "brand new file!"
git rebase --interactive <commit_id>^

a następnie możesz z łatwością dokończyć zmianę bazy bez konieczności zapamiętywania bardziej złożonych poleceń lub zatwierdzania wiadomości lub pisania.


To działa dla mnie. Zakładam, że jeśli chcesz dodać pliki z powrotem do miksu, po prostu użyj git add -A lub git add. i wrócili.
Alexander Mills

11

Korzystanie z git GUI może uprościć usuwanie pliku z wcześniejszego zatwierdzenia.

Zakładając, że nie jest to gałąź udostępniona i nie masz nic przeciwko przepisywaniu historii , uruchom:

git gui citool --amend

Możesz odznaczyć plik, który został błędnie popełniony, a następnie kliknąć „Zatwierdź”.

wprowadź opis zdjęcia tutaj

Plik jest usuwany z zatwierdzenia, ale będzie przechowywany na dysku . Więc jeśli odznaczyłeś plik po pomyłkowym dodaniu go, pojawi się on na liście nieśledzonych plików (a jeśli odznaczysz plik po pomyłkowej modyfikacji, pokaże się na twoich zmianach, które nie zostały ustawione na liście zatwierdzeń).


2
Na Ubuntu możesz zainstalować git gui zsudo apt-get install git-gui
JDiMatteo

Dziękuję Ci! Utknąłem z problemem (błędem?), W którym dodano folder zawierający repozytorium .git i wszystkie zwykłe polecenia usuwania nie działały. To jednak pomogło. Jest kilka zatwierdzeń z powrotem, najpierw wykorzystałem, git rebase -i HEAD~4a następnie uruchomiłem polecenie, aby otworzyć edytor. Kolejna uwaga: „Unstaging” można znaleźć w menu „Commit”.
Johny Skovdal,

Najłatwiejsze rozwiązanie ze wszystkich. Najłatwiejszy do zapamiętania. I znacznie mniej podatne na błędy niż używanie git reset --soft HEAD^(pamiętanie --soft arg), a następnie git commit -c ORIG_HEAD(zamiast --amend, co psuje wszystko).
Brent Faust

9

Jeśli chcesz zachować swoje zatwierdzenie (być może poświęciłeś już trochę czasu na napisanie szczegółowej wiadomości zatwierdzenia i nie chcesz jej zgubić) i chcesz tylko usunąć plik z zatwierdzenia, ale nie całkowicie z repozytorium:

git checkout origin/<remote-branch> <filename>
git commit --amend

6

Wykonaj sekwencję następujących poleceń:

//to remove the last commit, but preserve changes  
git reset --soft HEAD~1

//to remove unneded file from the staging area  
git reset HEAD `<your file>` 

//finally make a new commit  
git commit -m 'Your message'

Próbowałem wykonać następujące kroki i widzę ten błąd: nie udało się wypchnąć niektórych referencji do „git ...”. Aby zapobiec utracie historii, odrzucono aktualizacje niezwiązane z szybkim przesyłaniem. Scal zdalne zmiany (np. „git pull”) przed ponownym pchnięciem. Szczegółowe informacje można znaleźć w sekcji „Uwaga na temat szybkiego przewijania” w „git push --help”. (po git pull mam te same zmiany)
Dezigo

Oznacza to, że stan Twojego zdalnego repozytorium zmienił się podczas wykonywania lokalnej pracy. A po „git pull” lokalne zmiany powinny zostać scalone ze zdalnymi, to wszystko. Oczywiście twoje zmiany muszą pozostać.
Sergey Onishchenko

Innymi słowy, jeśli pojawi się ten błąd @Dezigo, dodaj flagę -f, aby wymusić aktualizację.
Jungledev

5

Chciałem tylko uzupełnić najwyższą odpowiedź, ponieważ musiałem uruchomić dodatkowe polecenie:

git reset --soft HEAD^
git checkout origin/master <filepath>

Twoje zdrowie!


Witamy. Ta odpowiedź byłaby lepsza, gdybyś wyjaśnił, co faktycznie robią polecenia.
Mark Chorley,

3

Coś, co zadziałało dla mnie, ale nadal uważam, że powinno być lepsze rozwiązanie:

$ git revert <commit_id>
$ git reset HEAD~1 --hard

Po prostu zostaw zmianę, którą chcesz odrzucić w drugim zatwierdzeniu, sprawdź inne

$ git commit --amend // or stash and rebase to <commit_id> to amend changes

3

git reset --soft HEAD^wycofuje zatwierdzenie, a kiedy piszesz git status, mówi ci, co masz zrobić:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

2

Myślę, że szybszym i łatwiejszym sposobem jest użycie interaktywnego trybu git rebase.

git rebase -i head~1  

(lub głowa ~ 4, jak daleko chcesz się posunąć)

a następnie zamiast „pick” użyj „edit”. Nie zdawałem sobie sprawy, jak potężna jest „edycja”.

https://www.youtube.com/watch?v=2dQosJaLN18

Mam nadzieję, że okaże się to pomocne.


wideo trwa 10 minut i nie jest tak przydatne
MolbOrg

2

Miałem ten sam problem, gdy mam zmiany w lokalnym oddziale, w którym chciałem przywrócić tylko jeden plik. Dla mnie zadziałało -

( funkcja / target_branch poniżej to miejsce, w którym mam wszystkie moje zmiany, w tym te, które chciałem cofnąć dla określonego pliku)

( origin / feature / target_branch to gałąź zdalna, do której chcę przekazać moje zmiany)

( funkcja / inscenizacja jest moją tymczasową gałęzią inscenizacji, w której będę wypychać wszystkie pożądane zmiany oprócz zmiany tego jednego pliku)

  1. Stwórz lokalną gałąź z mojego pochodzenia / funkcji / docelowej gałęzi - nazywanej to cechą / inscenizacją

  2. Połączyła moją pracę lokalnym oddziale fabularny / target_branch do funkcji / inscenizacja oddział

  3. Wyrejestrowany cecha / inscenizacja następnie git resetowania --soft ORIG_HEAD (obecnie wszystkie zmiany z funkcji / inscenizacji”odbędzie się jednak niezakończonej).

  4. Nieustawiony plik, który wcześniej sprawdziłem, z niepotrzebnymi zmianami

  5. Zmieniono odgałęzienie upstream dla feature / staging na origin / feature / target_branch

  6. Zatwierdził resztę zmian etapowych i przekazał do mojego zdalnego źródła / funkcji / docelowej gałęzi


1

Jeśli nie potrzebujesz już tego pliku, możesz to zrobić

git rm file
git commit --amend
git push origin branch

1

Jeśli używasz GitHub i jeszcze nie wypchnąłeś zatwierdzenia, GitHub Desktop łatwo rozwiązuje ten problem:

  1. Wybierz Repozytorium -> Cofnij ostatnie zatwierdzanie
  2. Odznacz plik, który został przez pomyłkę dodany. Twój poprzedni komunikat zatwierdzenia będzie już w oknie dialogowym.
  3. Naciśnij przycisk Commit!

1

Jeśli chcesz usunąć pliki z poprzednich zatwierdzeń, użyj filtrów

git filter-branch --prune-empty --index-filter 'git rm --ignore-unmatch --cached "file_to_be_removed.dmg"'

Jeśli widzisz ten błąd:

Nie można utworzyć nowej kopii zapasowej. Poprzednia kopia zapasowa już istnieje w refs / original / Force nadpisując kopię przy pomocy -f

Wystarczy usunąć kopie referencyjne na lokalnym repozytorium

$ rm -rf .git/refs/original/refs

1

jeśli jeszcze nie wypchniesz swoich zmian do git

git reset --soft HEAD~1

Zresetuje wszystkie zmiany i powróci do jednego zatwierdzenia z powrotem

Jeśli jest to ostatni zatwierdzony plik i chcesz usunąć plik z lokalnego i zdalnego repozytorium, spróbuj tego:

git rm <file>
 git commit --amend

lub nawet lepiej:

najpierw zresetuj

git reset --soft HEAD~1

zresetuj niechciany plik

git reset HEAD path/to/unwanted_file

popełnić ponownie

git commit -c ORIG_HEAD  

to samo co powyżej, ale nawet pomogło w sprawdzeniu
Reshma

0

Pracowałem nad tym, aby usunąć plik z repozytorium bitów, które początkowo wypchnąłem do gałęzi.

git checkout origin/develop <path-to-file>
git add <path-to-file>
git commit -m "Message"
git push

0

Skopiowałem bieżące pliki do innego folderu, a następnie pozbyłem się wszystkich niepoprawnych zmian poprzez:

git reset --hard @{u}

Następnie skopiuj rzeczy z powrotem. Commit, Push.


0

Możesz po prostu użyć tego polecenia:

git restore --staged <file>

0
Here is the step to remove files from Git Commit.

>git reset --soft HEAD^1(either commitid ) -- now files moved to the staging area.
>git rm --cached filename(it will removed the file from staging area)
>git commit -m 'meaningfull message'(Now commit the required files)

-1

Żadna z odpowiedzi w tym momencie nie jest rozsądna. Wygląda na to, że istnieje wystarczające zapotrzebowanie na zaproponowanie prawdziwego rozwiązania: https://github.com/git/git/blob/master/Documentation/SubmittingPatches

git --uncommit <nazwa pliku>

byłoby miło. Rozumiem, że nie chcemy modyfikować historii, ale jeśli jestem lokalny i przypadkowo dodałem lokalny plik „hack” i chcę go usunąć z zatwierdzenia, byłoby to bardzo pomocne.

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.