Git - Cofnij wypychanie zatwierdzeń

609

Mam projekt w zdalnym repozytorium, zsynchronizowanym z lokalnym repozytorium (programowanie) i serwerowym (prod). Wprowadziłem pewne zatwierdzone zmiany, które zostały już przekazane do zdalnego i zostały pobrane z serwera. Teraz chcę cofnąć te zmiany. Więc mógłbym tylko git checkoutzatwierdzić przed zmianami i zatwierdzić nowe zmiany, ale domyślam się, że będą problemy z wypchnięciem ich ponownie na odległość. Wszelkie sugestie dotyczące dalszego postępowania?

Manolo
źródło

Odpowiedzi:

735

Możesz cofnąć poszczególne zatwierdzenia za pomocą:

git revert <commit_hash>

Spowoduje to utworzenie nowego zatwierdzenia, które przywróci zmiany określonego przez Ciebie zatwierdzenia. Zauważ, że przywraca tylko to konkretne zatwierdzenie, a potem nie zatwierdza. Jeśli chcesz cofnąć zakres zatwierdzeń, możesz to zrobić w następujący sposób:

git revert <oldest_commit_hash>..<latest_commit_hash>

Odwraca zatwierdzenia między określonymi zatwierdzeniami i włącznie.

Spójrz na stronie man git-revert uzyskać więcej informacji na temat git revertpolecenia. Zobacz także tę odpowiedź, aby uzyskać więcej informacji na temat cofania zatwierdzeń.

gitaarik
źródło
22
Innymi słowy, powraca do <najstarszego_kolejnego polecenia>;)
David
7
@mr_jigsaw Usegit log
gitaarik
2
W dokumentacji git napisano, że polecenie revert przywraca zatwierdzenia między pierwszym a ostatnim zatwierdzeniem (zarówno pierwsze, jak i ostatnie zawarte). Zobacz dokumentację
Onur Demir
4
@aod jest poprawny, ta odpowiedź musi zostać zaktualizowana. obecny interfejs git API do przywracania znajduje <oldest_commit_hash>się na liście
powrotów
4
z git 2.17.2 cofnij <old>. <new> nie obejmuje starego, ale zawiera <nowy>
chingis
353

Rozwiązanie, które nie zachowuje śladów „cofnięcia”.

UWAGA: nie rób tego, jeśli ktoś już wyciągnął Twoją zmianę (użyłbym tego tylko na moim osobistym repozytorium)

zrobić:

git reset <previous label or sha1>

spowoduje to ponowne pobranie wszystkich aktualizacji lokalnie (więc status git wyświetli listę wszystkich zaktualizowanych plików)

następnie „wykonujesz swoją pracę” i ponownie zatwierdzasz zmiany (Uwaga: ten krok jest opcjonalny)

git commit -am "blabla"

W tej chwili Twoje lokalne drzewo różni się od zdalnego

git push -f <remote-name> <branch-name>

wypchnie i zmusi pilota do rozważenia tego wypchnięcia i usunięcia poprzedniego (określenie nazwy zdalnej i nazwy gałęzi nie jest obowiązkowe, ale zaleca się unikanie aktualizacji wszystkich gałęzi za pomocą flagi aktualizacji).

!! uważaj, niektóre tagi mogą nadal wskazywać usunięte zatwierdzenie !! how-to-delete-a-remote-tag

jo_
źródło
4
-a wszystkie śledzone pliki zostaną zatwierdzone -m następuje komunikat o zatwierdzeniu
jo_
3
Dokładnie to, czego szukałem. Ktoś popełnił błąd, popchnął i cofnął go później. Z tego powodu nie można było połączyć gałęzi i chciałem sprawić, by repozytorium znów było w poprawnym stanie (i
zrezygnowałem
1
Której „poprzedniej etykiety lub sha1” powinienem użyć? Czy powinienem wprowadzić ostatnią „poprawną” lub poprzednią i ponownie wykonać wszystkie zmiany wprowadzone przez ostatnią poprawną?
elysch
3
ten tuż przed błędnym zatwierdzeniem
jo_
1
Właśnie tego potrzebuję. Przez pomyłkę popchnąłem gałąź do opanowania. W rezultacie miałem wiele śmieci w trakcie całej historii. Właśnie zrobiłem git push -fostatnie poprawne zatwierdzenie i zdalne wyczyszczenie historii! Dzięki!
Anton Rybalko
193

W tych przypadkach robię:

  • Na serwerze przesuń kursor z powrotem do ostatniego znanego dobrego zatwierdzenia:

    git push -f origin <last_known_good_commit>:<branch_name>
    
  • Lokalnie wykonaj to samo:

    git reset --hard <last_known_good_commit>
    #         ^^^^^^
    #         optional
    



Zobacz pełny przykład gałęzi my_new_branch, którą utworzyłem w tym celu:

$ git branch
my_new_branch

Oto najnowsza historia po dodaniu kilku elementów do myfile.py:

$ git log
commit 80143bcaaca77963a47c211a9cbe664d5448d546
Author: me
Date:   Wed Mar 23 12:48:03 2016 +0100

    Adding new stuff in myfile.py

commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit

Chcę pozbyć się ostatniego zatwierdzenia, które już zostało wypchnięte, więc uruchamiam:

$ git push -f origin b4zad078237fa48746a4feb6517fa409f6bf238e:my_new_branch
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:me/myrepo.git
 + 80143bc...b4zad07 b4zad078237fa48746a4feb6517fa409f6bf238e -> my_new_branch (forced update)

Miły! Teraz widzę, że plik, który został zmieniony w tym commit ( myfile.py) pokazuje w "not staged for commit":

$ git status
On branch my_new_branch
Your branch is up-to-date with 'origin/my_new_branch'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   myfile.py

no changes added to commit (use "git add" and/or "git commit -a")

Ponieważ nie chcę tych zmian, po prostu przesuwam kursor lokalnie z powrotem:

$ git reset --hard b4zad078237fa48746a4feb6517fa409f6bf238e
HEAD is now at b4zad07 Initial commit

Teraz HEAD znajduje się w poprzednim zatwierdzeniu, zarówno lokalnym, jak i zdalnym:

$ git log
commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit
fedorqui „SO przestań szkodzić”
źródło
10
To poprawna odpowiedź! właśnie to trzeba zrobić w moim przypadku dzięki nauczyłem się dziś czegoś nowego :)
Egli Becerra
2
To poprawna odpowiedź! Chodzi o zatwierdzenia wypychane (!)!
powtac
3
Jeśli chcesz naprawdę cofnąć zmiany (tak jakbyś ich nigdy nie naciskał), to jest poprawna odpowiedź.
Jacob
1
Idealna odpowiedź. Działa zgodnie z oczekiwaniami!
RafiAlhamd
2
Ktoś kupi temu człowiekowi piwo!
Jay Nebhwani
72

Możesz ODWRÓCIĆ (lub możesz również nazwać to USUŃ ) Git Commit OBU lokalnie i zdalnie, jeśli wykonasz kroki podane poniżej za pomocą wiersza poleceń git.

Uruchom następujące polecenie, aby zobaczyć identyfikator zatwierdzenia, który chcesz przywrócić

git log --oneline --decorate --graph

Otrzymasz następujący zrzut ekranu wprowadź opis zdjęcia tutaj

Jeśli sprawdzisz także zdalnie (przez interfejs sieciowy) , zobaczysz, że byłoby to takie samo, jak pokazano poniżej

wprowadź opis zdjęcia tutaj

Zgodnie ze zrzutem ekranowym aktualnie zatwierdzasz identyfikator e110322, ale chcesz wrócić do 030bbf6 ZARÓWNO LOKALNIE i ZDALNIE .

Wykonaj następujące kroki, aby USUNĄĆ / ZWRÓCIĆ zatwierdzenia lokalnie + zdalnie


Najpierw przywracanie lokalne, aby zatwierdzić identyfikator 030bbf6

git reset --hard 030bbf6

śledzony przez

git clean -f -d

Te dwa polecenia wyczyść wymuszają resetowanie, aby zatwierdzić etap 030bbf6, jak pokazano poniżej na zdjęciu

wprowadź opis zdjęcia tutaj

teraz, jeśli uruchomisz status git, zobaczysz, że DWA Zatwierdzasz ZAZ zdalnej gałęzi, jak pokazano poniżej wprowadź opis zdjęcia tutaj

Uruchom następujące, aby zaktualizować swoje indeksy (jeśli są jakieś aktualizacje). Zaleca się, aby poprosić wszystkich programistów, aby nie przyjmowali żadnych żądań ściągania w głównym oddziale zdalnym.

git fetch --all

Kiedy to zrobisz, będziesz musiał wcisnąć to mocno , używając symbolu + przed gałęzią, jak pokazano poniżej. Użyłem tutaj jako gałęzi master , możesz ją zastąpić dowolną

wprowadź opis zdjęcia tutaj Kod

git push -u origin +master

teraz, jeśli zobaczysz interfejs sieciowy pilota, to zatwierdzenie również powinno zostać cofnięte.

wprowadź opis zdjęcia tutaj

vibs2006
źródło
61

Spowoduje to usunięcie wypychanych zatwierdzeń

git reset --hard 'xxxxx'

git clean -f -d

git push -f
Geneza Mo D.
źródło
7
Ta metoda poprawnie przepisuje historię, aby usunąć zatwierdzenie. Niesamowite
Jesse Reza Khorasanee
2
ta odpowiedź to el magnifeco!
truthadjustr
3
Uwielbiam odpowiedź, dziękuję :)
Dzenis H.
1
Żeby było jasne (nie byłem pewien): zatwierdzenie będzie bieżącym zatwierdzeniem po operacji. Nie ostatni do usunięcia.
Maik639
21
git revert HEAD -m 1

W powyższym wierszu kodu. „Ostatni argument reprezentuje”

  • 1 - cofa jedno zatwierdzenie.

  • 2 - przywraca ostatnie dwa zatwierdzenia.

  • n - cofa ostatnie n zatwierdzeń.

Musisz nacisnąć po tym poleceniu, aby zadziałać na pilocie. Masz inne opcje, takie jak określenie zakresu zatwierdzeń do przywrócenia. To jest jedna z opcji.


Później korzystanie git commit -am "COMMIT_MESSAGE" następnie git pushalbogit push -f

Sireesh Yarlagadda
źródło
8
To nie jest prawda - parametr -m określa liczbę elementów nadrzędnych, do których należy przywrócić (zazwyczaj 1, jeśli chcesz przywrócić przychodzące „ich” zmiany, w przeciwieństwie do 2 w przypadku zmian połączonych, „naszych” - w przypadku scalenia 2 commits). Nie ma to nic wspólnego z cofniętą liczbą zatwierdzeń - jeśli chcesz cofnąć zakres zatwierdzeń, użyjgit revert ref1..ref2
Null Reference
1
Nie
przyniósł
2

2020 Prosty sposób:

git reset <commit_hash>

(Hash ostatniego zatwierdzenia, który chcesz zachować).

Zachowasz teraz niezatwierdzone zmiany lokalnie.

Jeśli chcesz ponownie naciskać, musisz:

git push -f
Xys
źródło
0

Oto moja droga:

Powiedzmy, że nazwa oddziału to develop.

# Create a new temp branch based on one history commit
git checkout <last_known_good_commit_hash>
git checkout -b develop-temp

# Delete the original develop branch and 
# create a new branch with the same name based on the develop-temp branch
git branch -D develop
git checkout -b develop

# Force update this new branch
git push -f origin develop

# Remove the temp branch
git branch -D develop-temp
ukośnik odwrotny112
źródło
0

Możesz zrobić coś takiego

git push origin +<short_commit_sha>^:<branch_name>
avrsanjay
źródło