Pytanie Jak cofnąć ostatnie zatwierdzenia w Git?


Przypadkowo popełniłem złe pliki Git, ale nie przekazałem jeszcze zatwierdzenia na serwer.

Jak mogę cofnąć te zatwierdzenia z lokalnego repozytorium?


17823
2017-07-28 22:22


pochodzenie


Ostrzeżenie: powinieneś to zrobić tylko, jeśli jeszcze nie przekazałeś zatwierdzenia do zdalnego, w przeciwnym razie zepsujesz historię innych, którzy już wyciągnęli zatwierdzenie z pilota! - thSoft
Oto jest bardzo jasny i dokładny post o zgubieniu rzeczy w git, prosto z Githuba. - Nobita
Zobacz ten przewodnik dla cofania zatwierdzeń Git w oddziale lokalnym, publicznym i Git Jak cofnąć Git Commits jak pro - Luzan Baral
Zanim opublikujesz nową odpowiedź, zastanów się, czy jest już ponad 65 odpowiedzi na to pytanie. Upewnij się, że twoja odpowiedź przyczynia się do tego, czego nie ma wśród istniejących odpowiedzi. - Sazzad Hissain Khan
Wiesz, czego potrzebuje git? git undo, to jest to. Wtedy gówna reputacja, aby poradzić sobie z błędami popełnionymi przez nas, znikają zwykli śmiertelnicy. Wdrażaj, naciskając bieżący stan na stosie git przed wykonaniem jakiegokolwiek git dowództwo. Wpłynęłoby to na wydajność, więc najlepiej byłoby dodać flagę konfiguracji, czy włączyć tę opcję. - Yimin Rong


Odpowiedzi:


Cofnij zatwierdzenie i ponów

$ git commit -m "Something terribly misguided"             # (1)
$ git reset HEAD~                                          # (2)
<< edit files as necessary >>                              # (3)
$ git add ...                                              # (4)
$ git commit -c ORIG_HEAD                                  # (5)
  1. To właśnie chcesz cofnąć
  2. To pozostawia twoje działające drzewo (stan twoich plików na dysku) niezmienione, ale cofa zatwierdzenie i pozostawia zmiany zatwierdzone bez rejestracji (tak, że będą wyświetlane jako "Zmiany nie są wystawiane na zatwierdzenie" w git statusi musisz dodać je ponownie przed zatwierdzeniem). Jeśli ty tylko chcieć Dodaj więcej zmian poprzedniego zatwierdzenia lub zmień komunikat zatwierdzenia1, możesz użyć git reset --soft HEAD~ zamiast tego, co jest jak git reset HEAD~ (gdzie HEAD~ jest taki sam jak HEAD~1), ale pozostawia wprowadzone zmiany.
  3. Wprowadź poprawki do działających plików drzewa.
  4. git add wszystko, co chcesz dołączyć do nowego zatwierdzenia.
  5. Zatwierdź zmiany, ponownie wykorzystując stary komunikat zatwierdzenia. reset skopiowałem starą głowę do .git/ORIG_HEAD; commit z -c ORIG_HEAD otworzy edytor, który początkowo zawiera komunikat dziennika ze starego zatwierdzenia i pozwala na jego edycję. Jeśli nie musisz edytować wiadomości, możesz użyć -C opcja.

Pamiętaj jednak, że jeśli dodałeś nowe zmiany do indeksu, użyj commit --amend doda je do poprzedniego zatwierdzenia.

Jeśli kod jest już wysłany na twój serwer i masz uprawnienia do nadpisywania historii (rebase), to:

git push origin master --force

Możesz również spojrzeć na tę odpowiedź:

Jak przenieść HEAD z powrotem do poprzedniej lokalizacji? (Pojedyncza głowica)

Powyższa odpowiedź pokaże ci git reflog który służy do ustalenia, czym jest SHA-1, do którego chcesz powrócić. Po znalezieniu punktu, do którego chcesz cofnąć, użyj sekwencji poleceń, jak wyjaśniono powyżej.


1 Pamiętaj jednak, że nie musisz resetować do wcześniejszego zatwierdzenia, jeśli właśnie popełniłeś błąd Zatwierdź wiadomość. Najłatwiejszą opcją jest git reset (aby wprowadzić na scenę wszelkie zmiany wprowadzone od tego czasu), a następnie git commit --amend, który otworzy domyślny edytor wiadomości zatwierdzania, wypełniony ostatnim komunikatem o zatwierdzeniu.


19285
2018-06-16 17:27



A jeśli zatwierdzenie dotyczy niewłaściwej gałęzi, możesz git checkout theRightBranch ze wszystkimi etapami zmian. Tak jak właśnie musiałem. - Frank Shearar
Jeśli pracujesz w systemie DOS, zamiast git reset --soft HEAD^ musisz użyć git reset --soft HEAD~1. Znak ^ jest znakiem kontynuacji w systemie DOS, więc nie będzie działał poprawnie. Również, --soft jest domyślny, więc możesz go pominąć, jeśli chcesz i po prostu powiedz git reset HEAD~1. - Ryan Lundy
Również w zsh musisz cytować ^, więc git reset --soft 'HEAD^'... przynajmniej tak zrobiłem - jberryman
(Korekta tego, co napisałem powyżej; --mixed jest domyślny. --mixed oznacza zachować zmienione pliki, ale nie przechowywać ich w indeksie. --soft zachowa zmienione pliki i zachowa je w indeksie, tak jak przed zmianą zatwierdzenia. Przepraszam za zamieszanie.) - Ryan Lundy
Użytkownicy zsh mogą uzyskać: zsh: no matches found: HEAD^ - musisz uciec ^ tj. git reset --soft HEAD\^ - tnajdek


Cofanie zatwierdzenia jest trochę przerażające, jeśli nie wiesz, jak to działa. Ale naprawdę jest to łatwe, jeśli rozumiesz.

Powiedzmy, że masz to, gdzie C jest HEAD, a (F) jest stanem twoich plików.

   (F)
A-B-C
    ↑
  master

Chcesz nuke popełnij C i nigdy więcej go nie zobacz. Robisz to:

git reset --hard HEAD~1

Wynik to:

 (F)
A-B
  ↑
master

Teraz B to HEAD. Ponieważ użyłeś --hard, twoje pliki zostaną zresetowane do stanu w commit B.

Ach, ale załóżmy, że zatwierdzenie C nie było katastrofą, ale tylko trochę. Chcesz cofnij zatwierdzenie, ale zachowaj zmiany do edycji, zanim zrobisz lepsze zatwierdzenie. Zaczynając od tego miejsca, z C jako HEAD:

   (F)
A-B-C
    ↑
  master

Możesz to zrobić, pozostawiając wyłączony --hard:

git reset HEAD~1

W tym przypadku wynik jest następujący:

   (F)
A-B-C
  ↑
master

W obu przypadkach HEAD jest wskaźnikiem ostatniego zatwierdzenia. Kiedy robisz git reset HEAD~1, powiesz Gitowi, aby przesunął wskaźnik HEAD o jeden commit. Ale (chyba że używasz --hard) zostawiasz swoje pliki bez zmian. Więc teraz git status pokazuje zmiany, które sprawdziłeś w C. Nic nie straciłeś!

Aby uzyskać najlżejszy dotyk, możesz nawet cofnij zatwierdzenie, ale pozostaw swoje pliki i swoje indeks:

git reset --soft HEAD~1

To nie tylko pozostawia twoje pliki w spokoju, nawet zostawia twoje indeks sam. Kiedy to zrobisz git status, zobaczysz, że te same pliki są w indeksie jak wcześniej. W rzeczywistości, zaraz po tym poleceniu, możesz zrobić git commit i powtórzysz to samo, co właśnie zrobiłeś.

Jeszcze jedna rzecz: Przypuśćmy, że zniszczysz commit tak jak w pierwszym przykładzie, ale potem odkryjesz, że tego potrzebujesz? Trudno, prawda?

Nie, jest nadal sposób na odzyskanie go. Rodzaj git reflog i zobaczysz listę (częściowych) zatwierdzeń, które zostały przeniesione. Znajdź zatwierdzony plik, i wykonaj następujące czynności:

git checkout -b someNewBranchName shaYouDestroyed

Właśnie wskrzesiłeś to zatwierdzenie. Zobowiązania w rzeczywistości nie są niszczone w Git przez jakieś 90 dni, więc zazwyczaj możesz wrócić i uratować kogoś, czego nie chciałeś się pozbyć.


9734
2018-05-29 18:16



@dma_k, tak. Lub możesz zrobić git reset --hard HEAD^^ pewnego razu. Używam notacji tyldy (~), ponieważ notacja caret (^) nie działa w DOS. - Ryan Lundy
Kolejna fajna wskazówka: możesz ponownie dołączyć gałąź do zatwierdzenia, z którego ją usunąłeś git branch -f <branch> <commit-id>. Oszczędność konieczności ponownego tworzenia commitów! - naught101
Dla początkujących git nie jest oczywiste, jaka jest różnica między dwiema ostatnimi opcjami (-soft i the above above). Wspomnienie indeksu nie pomaga, tak naprawdę nie wiemy jeszcze, co to oznacza. Połączenie @ nessur między soft i Ctrl-Z naprawdę pomogło! Ale nadal nie rozumiem różnicy między tymi dwiema opcjami. - Stomp
O wiele lepiej jest powiedzieć "dlaczego" coś działa, niż po prostu usłyszeć odpowiedź. Uznanie dla tego opisu - pomogło to "dostać" git. - Chris Nash
Brakujący kluczowy punkt: jeśli wspomniane zatwierdzenie zostało wcześniej "przekazane" do zdalnego, każda operacja "cofnij", nie ważne jak prosto, spowoduje ogromny ból i cierpienie reszcie użytkowników, którzy mają to zatwierdzenie w swojej lokalnej kopii, kiedy robią "git pull" w przyszłości. Tak więc, jeśli zatwierdzenie zostało już "pchnięte", wykonaj to zamiast: git revert <bad-commit-sha1-id> git push origin: - FractalSpace


Zajęło mi to trochę czasu, więc może to pomoże komuś ...

Istnieją dwa sposoby "cofnięcia" ostatniego zatwierdzenia, w zależności od tego, czy już zatwierdziłeś publiczne zatwierdzenie (przekazane do zdalnego repozytorium):

Jak cofnąć lokalny commit

Powiedzmy, że popełniłem lokalnie, ale teraz chcę usunąć to zatwierdzenie.

git log
    commit 101: bad commit    # latest commit, this would be called 'HEAD'
    commit 100: good commit   # second to last commit, this is the one we want

Aby przywrócić wszystko z powrotem do stanu sprzed ostatniego zatwierdzenia, musimy reset do wcześniejszego zatwierdzenia HEAD:

git reset --soft HEAD^     # use --soft if you want to keep your changes
git reset --hard HEAD^     # use --hard if you don't care about keeping the changes you made

Teraz git log pokaże, że nasze ostatnie zatwierdzenie zostało usunięte.

Jak cofnąć publiczne zatwierdzenie

Jeśli twoje commity zostały już upublicznione, będziesz chciał utworzyć nowe zatwierdzenie, które "przywróci" zmiany wprowadzone w poprzednim zatwierdzeniu (bieżące HEAD).

git revert HEAD

Twoje zmiany zostaną teraz cofnięte i gotowe do zatwierdzenia:

git commit -m 'restoring the file I removed by accident'
git log
    commit 102: restoring the file I removed by accident
    commit 101: removing a file we don't need
    commit 100: adding a file that we need

Aby uzyskać więcej informacji, sprawdź Podstawy Git - Cofanie rzeczy


1751
2018-05-29 18:13



Uważam, że ta odpowiedź jest najczystsza. git revert HEAD^ nie jest poprzednim, jest poprzednim z poprzedniego. Zrobiłem : git revert HEAD a następnie naciśnij ponownie i zadziałało :) - nacho4d
@riezebosch: twoje ostrzeżenie jest w niewłaściwym miejscu. Ta odpowiedź nie psuje rzeczy, ponieważ poprawnie tworzy nowy commit 102: "przywracanie usuniętego pliku w razie wypadku" - rubo77
To najlepsza odpowiedź, ponieważ nie miesza się z historią git - Lukas


Dodaj / usuń pliki, aby uzyskać rzeczy, które chcesz:

git rm classdir
git add sourcedir

Następnie zmień zatwierdzenie:

git commit --amend

Poprzednie, błędne zatwierdzenie zostanie zmienione w celu odzwierciedlenia nowego stanu indeksu - innymi słowy, będzie tak, jakbyś nigdy nie popełnił błędu.

Zauważ, że powinieneś to zrobić tylko, jeśli jeszcze nie pchnąłeś. Jeśli popchnąłeś, to musisz po prostu zatwierdzić poprawkę normalnie.


1625
2017-07-31 09:39



Czy to działa, gdy zrobiłem git commit --amend i co naprawdę zamierzałem zrobić, to git commit? - dbm
@dbm, jeśli przypadkowo zmieniono, użyj git reset --soft <oldref>, gdzie oldref to identyfikator commit przed zmianą. Możesz użyć git reflog aby zidentyfikować stary identyfikator zatwierdzenia. Spowoduje to cofnięcie skutków zmiany, ale pozostawi zmiany w ustawieniach. Więc po prostu zrób git commit popełnić jako zwykły commit. - bdonlan
@Dennis, git commit --amend zmienia bieżące drzewo (np. Zmiany etapowe) w zatwierdzenie, zastępując bieżącą HEAD. Po tym etapie nie są już uznawane za wystawiane, ponieważ są częścią commit (tj. Git diff --cached jest puste), ale nie są "usunięte" lub "zagubione". - bdonlan


git rm yourfiles/*.class
git commit -a -m "deleted all class files in folder 'yourfiles'"

lub

git reset --hard HEAD~1

Ostrzeżenie: Powyższe polecenie spowoduje trwałe usunięcie modyfikacji .java pliki (i inne pliki), które chcesz zatwierdzić.

The hard reset do HEAD-1 ustawi twoją kopię roboczą na stan zatwierdzenia przed błędnym zatwierdzeniem.


878
2018-05-25 16:04



"--hard" pozbędzie się zmodyfikowanych plików .java w katalogu roboczym, który chciał zatwierdzić. - Esko Luontola
Możesz "git zapisać" zmiany kopii roboczej, wykonaj twardy reset, a następnie "git ukryj pop", aby je odzyskać, choć przypuszczam, że miękki reset byłby prostszy. - Asad R.
git commit -a -m "" lub git commit -am "" naturalnie! :] - trejder
Kolejne "skrótowe" użycie skrytki; jeśli chcesz wszystko odświeżyć (cofnij dodanie git), po prostu git stash, następnie git stash pop - seanriordan08


Aby zmienić ostatnie zatwierdzenie

Zastąp pliki w indeksie:

git rm --cached *.class
git add *.java

Następnie, jeśli jest to oddział prywatny, modyfikować commit:

git commit --amend

Lub, jeśli jest to dzielona gałąź, dokonaj nowego zatwierdzenia:

git commit -m 'Replace .class files with .java files'


(zmienić poprzednie zatwierdzenie, użyj niesamowitego interaktywny rebase)


ProTip: Dodaj *.class do a gitignore aby to powtórzyć.


Aby przywrócić zatwierdzenie

Zmiana zatwierdzenia jest idealnym rozwiązaniem, jeśli musisz zmienić ostatnie zatwierdzenie, ale bardziej ogólnym rozwiązaniem jest reset.

Możesz zresetować git do dowolnego zatwierdzenia za pomocą:

git reset @~N

Gdzie N to liczba wcześniejszych zatwierdzeń HEAD, i @~ resetuje do poprzedniego zatwierdzenia.

Zamiast więc zmienić zatwierdzenie, możesz użyć:

git reset @~
git add *.java
git commit -m "Add .java files"

Sprawdzić git help reset, w szczególności sekcje na --soft  --mixed i --hard, dla lepszego zrozumienia tego, co to robi.

Reflog

Jeśli się zepsułeś, zawsze możesz użyć refloga, aby znaleźć upuszczone zatwierdzenia:

$ git reset @~
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~
2c52489 HEAD@{1}: commit: added some .class files
$ git reset 2c52489
... and you're back where you started



679
2018-01-31 07:06



Dla tych, którzy czytają w przyszłości - proszę zauważyć, że git revert jest oddzielnym poleceniem - które zasadniczo "resetuje" pojedynczy commimt. - BKSpurgeon


Posługiwać się git revert commit-id

Aby uzyskać identyfikator zatwierdzenia, po prostu użyj git log


549
2017-12-13 10:18



Jeśli popełniłeś błąd w niewłaściwym oddziale: po przywróceniu, przełącz się na właściwą gałąź i wybierz zatwierdzenie. - Kris
Co to znaczy, wiśnia wybierz commit? W moim przypadku znajdowałem się w niewłaściwym oddziale, gdy edytowałem plik. Popełniłem to wtedy zdałem sobie sprawę, że jestem w niewłaściwym oddziale. Użycie "git reset --soft HEAD ~ 1" spowodowało, że wróciłem do momentu tuż przed zatwierdzeniem, ale teraz, gdy sprawdzę poprawną gałąź, jak cofnąć zmiany w pliku w niewłaściwym oddziale, ale zamiast tego zrobić (w tym samym imieniu plik) w poprawnej gałęzi? - astronomerdave
Właśnie wykorzystałem git revert commit-id pracował jak urok. Oczywiście wtedy będziesz musiał popchnąć swoje zmiany. - Casey Robinson
Wierzę, że tak właśnie będzie git cherry-pick <<erroneous-commit-sha>> @astronomerdave. Od, Pan Prawie 2-lat-Late-to-the-Party. - Tom Howard


Jeśli planujesz całkowicie cofnąć lokalne zatwierdzenie, bez względu na zmiany wprowadzone w zatwierdzeniu, a jeśli nic się nie dzieje, po prostu wykonaj następujące polecenie.

git reset --hard HEAD^1

(To polecenie zignoruje cały twój commit, a twoje zmiany zostaną całkowicie utracone z twojego lokalnego drzewa roboczego). Jeśli chcesz cofnąć zatwierdzenie, ale chcesz zmiany w obszarze przemieszczania (przed zatwierdzeniem, tak jak po git add), a następnie wykonaj następujące polecenie.

git reset --soft HEAD^1

Teraz zatwierdzone pliki trafiają do obszaru przemieszczania. Załóżmy, że jeśli chcesz otworzyć pliki, ponieważ musisz zmodyfikować błędną wartość, wykonaj następujące polecenie

git reset HEAD

Teraz zatwierdzone pliki pochodzą z obszaru etapowego w obszar niezarządzany. Teraz pliki są gotowe do edycji, więc bez względu na to, co zmienisz, chcesz przejść do edycji i dodać ją i wykonać nowe / nowe zatwierdzenie.

Jeszcze


441
2018-04-06 13:58



@SMR, W twoim przykładzie wszystkie wskazują tylko bieżącą HEAD. HEAD ^ = HEAD ^ 1. Jak również HEAD ^ 1 = HEAD ~ 1. Gdy używasz HEAD ~ 2, istnieje różnica między symbolami ~ i ^. Jeśli użyjesz ~ 2, oznacza "pierwszy rodzic pierwszego rodzica" lub "dziadkowie". - Madhan Ayyasamy
jasne i łatwe do zrozumienia, uratuj moją noc! - Vladimir Ch
Najwyraźniej przypadkowo odrzucam tę odpowiedź i jest już za późno, abym mógł ją anulować. Przeprosiny. - Matt


Jeśli masz Git Extras zainstalowany, możesz uruchomić git undo aby cofnąć ostatnie zatwierdzenie. git undo 3 cofnie 3 ostatnie zatwierdzenia.


431
2017-10-25 03:41