Pytanie Jak przywrócić repozytorium Git do poprzedniego zatwierdzenia


Jak mogę powrócić z mojego bieżącego stanu do migawki wykonanej przy określonym zatwierdzeniu?

Jeśli zrobię git log, a następnie otrzymuję następujące wyniki:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <me@me.com>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <me@me.com>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <me@me.com>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <me@me.com>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

Jak powrócić do zatwierdzenia od 3 listopada, tj. Zatwierdzić 0d1d7fc?


6021
2017-11-06 16:58


pochodzenie


Związane z Jak cofnąć ostatni commit Git?.
Oto jest bardzo jasny i dokładny post o zgubieniu rzeczy w git, prosto z Githuba. - Nobita
Związane z: Przywróć stary commit Git w publicznym repozytorium. Należy zauważyć, że to pytanie dodaje ograniczenie, że repozytorium jest publiczne.
Uwielbiam git, ale fakt, że jest 35 odpowiedzi na coś, co powinno być niewiarygodnie proste, obnaża ogromny problem z git. A może to doktorzy? - The Muffin Man


Odpowiedzi:


To zależy w dużej mierze od tego, co masz na myśli przez "przywrócić".

Tymczasowo przełącz się na inne zatwierdzenie

Jeśli chcesz tymczasowo do niego wrócić, wygłupiać się, a potem wrócić do miejsca, w którym się znajdujesz, musisz tylko sprawdzić żądane zatwierdzenie:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Lub jeśli chcesz popełnić commit, gdy tam jesteś, śmiało, aby utworzyć nowy oddział, gdy jesteś na tym:

git checkout -b old-state 0d1d7fc32

Aby wrócić do miejsca, w którym byłeś, po prostu sprawdź oddział, w którym byłeś ponownie. (Jeśli dokonałeś zmian, jak zawsze przy przełączaniu gałęzi, będziesz musiał sobie z nimi poradzić, możesz je zresetować, aby je wyrzucić, możesz ukryć, sprawdzić, ukryć pop, aby zabrać je ze sobą; je do oddziału tam, jeśli chcesz tam oddział.)

Twarde usuwanie niepublikowanych zatwierdzeń

Jeśli, z drugiej strony, chcesz naprawdę pozbyć się wszystkiego, co robiłeś od tego czasu, są dwie możliwości. Po pierwsze, jeśli nie opublikowałeś żadnego z tych zatwierdzeń, po prostu zresetuj:

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

Jeśli się zepsułeś, już wyrzuciłeś lokalne zmiany, ale możesz przynajmniej wrócić do poprzedniego miejsca, resetując ponownie.

Cofnij opublikowane zatwierdzenia z nowymi zatwierdzeniami

Z drugiej strony, jeśli opublikowałeś pracę, prawdopodobnie nie chcesz resetować gałęzi, ponieważ jest to skuteczne przepisywanie historii. W takim przypadku możesz rzeczywiście przywrócić zatwierdzenia. Z Git, przywracanie ma bardzo konkretne znaczenie: Utwórz commit z odwrotną poprawką, aby go anulować. W ten sposób nie przepisujesz żadnej historii.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

The git-revert manpage w dużej mierze obejmuje to w swoim opisie. Innym przydatnym linkiem jest ta sekcja git-scm.com omawiająca git-revert.

Jeśli zdecydujesz, że mimo wszystko nie chcesz się wycofać, możesz przywrócić cofnięcie (tak jak opisano tutaj) lub zresetować ponownie przed cofnięciem (zobacz poprzednią sekcję).

Pomocna może być również ta odpowiedź w tym przypadku:
Jak przenieść HEAD z powrotem do poprzedniej lokalizacji? (Pojedyncza głowica)


7841
2017-11-06 17:04



@ Rod komentarz na git revert HEAD~3 jako najlepszy wat do powrotu 3 zobowiązania są ważną konwencją. - New Alexandria
Czy mógłbyś napisać cały numer? lubić: git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50 - Spoeken
@MathiasMadsenStav Tak, możesz oczywiście określić zatwierdzenia przez pełny SHA1. Użyłem skróconych skrótów, aby odpowiedź była bardziej czytelna, a Ty też masz tendencję do korzystania z nich, jeśli piszesz. Jeśli kopiujesz i wklejasz, używaj pełnego skrótu. Widzieć Określanie zmian w rev revsese man git dla pełnego opisu, jak można nazwać zatwierdzenia. - Cascabel
Aby powrócić do bieżącego polecenia, polecenie "git checkout master" - Xavier John
Możesz użyć git revert --no-commit hash1 hash2 ... a potem po prostu zatwierdzaj każde odwrócenie w jednym zatwierdzeniu git commit -m "Message" - Mirko Akov


Przywracanie kopii roboczej do najnowszego zatwierdzenia

Aby powrócić do poprzedniego zatwierdzenia, ignorując wszelkie zmiany:

git reset --hard HEAD

gdzie HEAD jest ostatnim zatwierdzeniem w twoim bieżącym oddziale

Przywracanie kopii roboczej do starszego polecenia

Aby powrócić do zatwierdzenia starszego niż najnowszy commit:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Kredyty trafiają do podobnego pytania Stack Overflow, Powrócić do zatwierdzenia przez skrót SHA w Git?.


1262
2017-08-21 06:19



Zrobiłem to, ale potem nie byłem w stanie zatwierdzić i przesłać do zdalnego repozytorium. Chcę określonego starszego zobowiązania, by zostać HEAD ... - Lennon
Oznacza to, że już wprowadziłeś zatwierdzenia, które chcesz przywrócić. Może powodować wiele problemów dla osób, które wypróbowały Twój kod i pracują nad nim. Ponieważ nie mogą zastosować Twojego zatwierdzenia gładko nad swoim. W takim przypadku lepiej przywrócić git. Jeśli jesteś jedynym użytkownikiem repo. Zrób git push -f (Ale pomyśl dwa razy zanim to zrobisz) - vinothkr
Obowiązkowe Ostrzeżenie: nie resetuj mocno jeśli dzielisz swój oddział z innymi osobami, które mają kopie starych zatwierdzeń, ponieważ użycie takiego twardego resetu zmusi ich do ponownej synchronizacji pracy z nowo zresetowanym oddziałem. Miękki reset jest jednak bezpieczny, podobnie jak ostatnie rozwiązania w ta odpowiedź.
Chciałbym również zwrócić uwagę, że alternatywnie dla miękkiego resetowania, zamiast robić mieszany reset jako pierwszy i twardy reset jako ostatni, można wykonać twardy reset w następujący sposób: git reset --hard 56e05fc; git reset --soft HEAD@{1}; git commit.
@nuton linus pauling siebie, twórca git, skrytykował go za zbyt skomplikowane. Zapisał, że był "zszokowany", że Git stał się tak popularny, biorąc pod uwagę jego złożoność - boulder_ruby


Mnóstwo skomplikowanych i niebezpiecznych odpowiedzi tutaj, ale w rzeczywistości jest to łatwe:

git revert --no-commit 0766c053..HEAD
git commit

Spowoduje to przywrócenie wszystkiego z HEAD do wartości skrótu commit, co oznacza, że ​​ponownie utworzy stan zatwierdzenia w drzewie roboczym jak gdyby każde zobowiązanie od czasu, gdy wróciłem. Możesz następnie zatwierdzić bieżące drzewo, i utworzy całkiem nowy commit, który jest zasadniczo równoznaczny z zatwierdzeniem, do którego "przywróciłeś".

(The --no-commit flag pozwala git przywracać wszystkie zatwierdzenia naraz - w przeciwnym razie zostaniesz poproszony o wiadomość dla każdego zatwierdzenia w zakresie, zaśmiecając swoją historię niepotrzebnymi nowymi zatwierdzeniami).

To jest bezpieczny i łatwy sposób przywrócenia poprzedniego stanu. Żadna historia nie jest zniszczona, więc może być używana do zatwierdzeń, które zostały już upublicznione.


1221
2018-02-12 04:18



Jeśli naprawdę chcesz mieć indywidualne zatwierdzenia (zamiast cofania wszystkiego za pomocą jednego dużego zatwierdzenia), możesz przejść --no-edit zamiast --no-commit, aby nie trzeba było edytować komunikatu zatwierdzenia dla każdej rewersji.
Jeśli jedno z zatwierdzeń między 0766c053..HEAD jest scaleniem, wówczas pojawi się błąd (do zrobienia z nie -m określonym). Może to pomóc osobom napotykającym: stackoverflow.com/questions/5970889/... - timhc22
Aby zobaczyć różnice przed użyciem git diff --cached. - John Erck
$ git revert --no-commit 53742ae..HEAD zwraca fatal: empty commit set passed - Alex G
@AlexG, ponieważ musisz wprowadzić skrót wcześniej ten, do którego chcesz wrócić. W moim przypadku hasze były jak: 81bcc9e HEAD{0}; e475924 HEAD{1}, ... (od git reflog), i chciałem cofnąć to, co zrobiłem 81bcc9ewtedy musiałem zrobić git revert e475924..HEAD - EpicPandaForce


Najlepsza opcja dla mnie i prawdopodobnie dla innych to opcja resetowania Git:

git reset --hard <commidId> && git clean -f

To była dla mnie najlepsza opcja! Jest prosty, szybki i skuteczny!


Uwaga :  Jak wspomniano w komentarzach, nie rób tego, jeśli dzielisz swój oddział z innymi osobami, które mają kopie starych zatwierdzeń

Również z komentarzy, jeśli chcesz mniej "balowej" metody, której możesz użyć

git clean -i 


153
2017-10-22 11:53



Obowiązkowe Ostrzeżenie: nie rób tego jeśli dzielisz swój oddział z innymi osobami, które mają kopie starych zatwierdzeń, ponieważ użycie takiego twardego resetu zmusi ich do ponownej synchronizacji pracy z nowo zresetowanym oddziałem. Dla rozwiązania, które szczegółowo wyjaśnia, w jaki sposób bezpiecznie przywracać zatwierdzenia bez utraty pracy z twardym resetem, zobacz tę odpowiedź.
Po drugie ostrzeżenie o ciasteczku ... bądźcie świadomi konsekwencji. Zauważ jednak, że jeśli naprawdę potrzebujesz, aby te zatwierdzenia zniknęły z historii na zawsze, ta metoda resetowania + wyczyszczenia zrobi to i będziesz potrzebować siła wypchnij zmodyfikowane gałęzie z powrotem do wszystkich pilotów. - ashnazg
pamiętaj, że wyczyści pliki / foldery, takie jak .idea (phpstorm) lub .vagrant (vagrant), które mogą być użyte przez twoją konfigurację / IDE! - timhc22
git clean -f NIEBEZPIECZEŃSTWO NIEBEZPIECZEŃSTWO - Tisch
@Pogrindis - mnóstwo dobrych odpowiedzi tutaj, które nie usuwają nieśledzonych plików. - Tisch


Jeśli chcesz "anulować", skasować ostatnią wiadomość zatwierdzającą i przywrócić zmodyfikowane pliki do przemieszczania, użyj polecenia:

git reset --soft HEAD~1
  • --soft wskazuje, że niezatwierdzone pliki powinny zostać zachowane jako działające pliki przeciwne --hard które by je odrzuciły.
  • HEAD~1 jest ostatnim zatwierdzeniem. Jeśli chcesz wycofać 3 remisy, możesz użyć HEAD~3. Jeśli chcesz przywrócić określony numer wersji, możesz to również zrobić, używając skrótu SHA.

Jest to bardzo przydatne polecenie w sytuacjach, w których popełniłeś błąd i chcesz cofnąć ostatnie zatwierdzenie.

Źródło: http://nakkaya.com/2009/09/24/git-delete-last-commit/


103
2018-03-04 17:25



Jest to miękkie i delikatne: bez ryzyka, jeśli nie pchnąłeś swojej pracy - nilsM


Przed udzieleniem odpowiedzi dodajmy trochę tła, wyjaśniając, co to jest HEAD jest.

First of all what is HEAD?

HEAD jest po prostu odwołaniem do bieżącego zatwierdzenia (najnowszego) w bieżącym oddziale. Może być tylko jeden HEAD w dowolnym momencie (z wyłączeniem git worktree).

Zawartość HEAD jest przechowywane w środku .git/HEADi zawiera 40 bajtów SHA-1 bieżącego zatwierdzenia.


detached HEAD

Jeśli nie masz najnowszego zatwierdzenia - oznacza to HEAD wskazuje na wcześniejsze zatwierdzenie w historii, to się nazywa detached HEAD.

Enter image description here

W linii poleceń będzie wyglądać tak: SHA-1 zamiast nazwy oddziału od HEAD nie wskazuje wierzchołka bieżącego oddziału:

Enter image description here


Kilka opcji odzyskiwania z odłączonej głowicy HEAD:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Spowoduje to pobranie nowego oddziału wskazującego żądany commit. To polecenie spowoduje pobranie do zatwierdzenia.

W tym momencie możesz utworzyć oddział i zacząć pracę od tego momentu:

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Zawsze możesz skorzystać z reflog także. git reflog wyświetli dowolną zmianę, która zaktualizowała HEAD i sprawdzenie pożądanego wpisu do reflonu ustawi HEAD wróć do tego zatwierdzenia.

Za każdym razem, gdy HEAD zostanie zmodyfikowany, pojawi się nowy wpis w pliku reflog

git reflog
git checkout HEAD@{...}

Spowoduje to powrót do żądanego zatwierdzenia

Enter image description here


git reset HEAD --hard <commit_id>

"Przenieś" głowę z powrotem do pożądanego zatwierdzenia.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Uwaga: (Od Git 2.7) możesz również użyć git rebase --no-autostash także.

Schemat ten ilustruje, które polecenie wykonuje co. Jak widzisz reset && checkout zmodyfikuj HEAD.

Enter image description here


102
2018-02-05 21:56



Doskonała wskazówka do git reflog, dokładnie tego potrzebowałem - smac89
Oooo! To wszystko wydaje się być bardzo skomplikowane ... czy nie istnieje proste polecenie, które po prostu cofnie cię o krok? Jak przejście z wersji 1.1 w projekcie do wersji 1.0? Spodziewałbym się czegoś takiego: git stepback_one_commit lub coś .... - Kokodoko
jest: git reset HEAD^ --hard` - CodeWizard
@Kokodoko Tak, to jest strasznie skomplikowane ... i doskonały przykład tego, jak niewiele osób zastanawia się dla osób, które dopiero zaczynają. Zapoznaj się z moją odpowiedzią tutaj, a także z książką, którą polecam w niej. Git NIE jest czymś, co możesz po prostu intuicyjnie odebrać. I mogę być absolutnie pewien, że CodeWizard tego nie zrobił. - mike rodent


Próbowałem na wiele sposobów, aby przywrócić lokalne zmiany w Git i wydaje się, że to działa najlepiej, jeśli po prostu chcesz powrócić do ostatniego stanu zatwierdzenia.

git add . && git checkout master -f

Krótki opis:

  • NIE utworzy żadnych zatwierdzeń jako git revert robi.
  • NIE oddzieli HEAD jak git checkout <commithashcode> robi.
  • OZNACZY wszystkie lokalne zmiany i USUŃ wszystkie dodane pliki od ostatniego zatwierdzenia w oddziale.
  • Działa tylko z nazwami gałęzi, więc możesz w ten sposób przywrócić tylko ostatnie zatwierdzenie w oddziale.

Znalazłem znacznie wygodniejszy i prosty sposób na osiągnięcie powyższych wyników:

git add . && git reset --hard HEAD

gdzie HEAD wskazuje na ostatnie zatwierdzenie w bieżącym oddziale.

Jest to ten sam kod, który zasugerował boulder_ruby, ale dodałem git add . przed git reset --hard HEAD aby usunąć wszystkie nowe pliki utworzone od czasu ostatniego zatwierdzenia, ponieważ jest to to, czego większość ludzi oczekuje, gdy powrócę do ostatniego zatwierdzenia.


96
2017-07-29 11:01