Jak korzystać z Git Revert

110

Jak jest git revertużywany?

To może brzmieć jak duplikatu pytanie, ale kiedy ludzie pytają go, odpowiedź jest często stosowanie git resetzgodnie przywrócić zatwierdzenie przez hash SHA w Git?

Następnie, gdy ktoś zapyta, jak używać, git resetludzie odpowiedzą, że powinieneś użyć git revertzgodnie z Git - jak wycofać

Zanim się zorientujesz, pojawiło się 8 różnych ludzi z własnymi unikalnymi sposobami uratowania tyłka OP, z których wszystkie są nad twoją głową.

Więc spróbujmy trzymać się briefu i napisać przewodnik dla opornych git revert.

Scenariusz: dwukrotnie zobowiązałeś się do opanowania i jest zły. Popchnąłeś, a inni ludzie mają złe zmiany.

Chcesz to cofnąć. Nie jest to coś, co można ręcznie cofnąć w kodzie, powiedzmy, że jakiś kreator lub menedżer pakietów zmienił mnóstwo rzeczy w każdym miejscu - po prostu chcesz to wszystko przywrócić, jak było.

Na tym polega kontrola źródła. Jestem pewien, że to łatwe.

Okay, będziesz używać git revert ale jak?

I po biegu git revert musisz robić coś innego? Czy musisz zatwierdzić zmiany, cofnąć wprowadzone zmiany, czy przywrócić bezpośrednie zobowiązanie do repozytorium, czy co?

Oczywiście będziesz musiał ponownie naciskać i prawdopodobnie ogłosić swoje piłki zespołowi.

Luke Puplett
źródło

Odpowiedzi:

124

git revert tworzy nowe zatwierdzenie

git revert po prostu tworzy nowe zatwierdzenie, które jest przeciwieństwem istniejącego zatwierdzenia.

Pozostawia pliki w tym samym stanie, jakby przywrócone zatwierdzenie nigdy nie istniało. Na przykład rozważmy następujący prosty przykład:

$ cd /tmp/example
$ git init
Initialized empty Git repository in /tmp/example/.git/
$ echo "Initial text" > README.md
$ git add README.md
$ git commit -m "initial commit"
[master (root-commit) 3f7522e] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
$ echo "bad update" > README.md 
$ git commit -am "bad update"
[master a1b9870] bad update
 1 file changed, 1 insertion(+), 1 deletion(-)

W tym przykładzie historia zmian zawiera dwa zatwierdzenia, a ostatnia jest błędem. Korzystanie z Git Revert:

$ git revert HEAD
[master 1db4eeb] Revert "bad update"
 1 file changed, 1 insertion(+), 1 deletion(-)

W dzienniku będą 3 zatwierdzenia:

$ git log --oneline
1db4eeb Revert "bad update"
a1b9870 bad update
3f7522e initial commit

Więc istnieje spójna historia tego, co się stało, ale pliki wyglądają tak, jakby zła aktualizacja nigdy nie miała miejsca:

cat README.md 
Initial text

Nie ma znaczenia, gdzie w historii znajduje się zatwierdzenie do przywrócenia (w powyższym przykładzie ostatnie zatwierdzenie jest cofane - każde zatwierdzenie można cofnąć).

Pytania końcowe

czy potem musisz zrobić coś innego?

A git revertto po prostu kolejny zatwierdzenie, więc np. Wypchnij do pilota, aby inni użytkownicy mogli pobrać / pobrać / scalić zmiany i gotowe.

Czy musisz zatwierdzić zmiany, które zostały przywrócone, czy też przywrócenie jest bezpośrednio związane z repozytorium?

git revert jest zatwierdzeniem - nie ma dodatkowych kroków zakładających, że przywrócenie pojedynczego zatwierdzenia jest tym, co chciałeś zrobić.

Oczywiście będziesz musiał ponownie naciskać i prawdopodobnie ogłosić to zespołowi.

Rzeczywiście - jeśli pilot jest w niestabilnym stanie - poinformowanie reszty zespołu, że muszą go pociągnąć, aby uzyskać poprawkę (cofające zatwierdzenie), byłoby właściwą rzeczą do zrobienia :).

AD7six
źródło
Dla potwierdzenia, zarówno do pierwszego stwierdzenia tutaj, jak i do każdego, kto zastanawiał się nad tym samym. Zastanawiałem się tylko, jak to działa, możesz cofnąć przywrócenie, w którym jest kilka nowych zatwierdzeń od przywrócenia, które przywracasz. Tak więc powrót naprawdę jest po prostu zatwierdzeniem przeciwieństwa cofniętego zatwierdzenia. Oczywiście możesz mieć konflikty ... ale to inna historia.
GG2
Zawsze uważam, że lepiej jest unikać angażowania się w to, tylko po to, aby najpierw przejrzeć zmiany i użyć, git revert -n <commitToRevet> lub git revert --no-commit <commitToRevet>
Eklavyaa
2
Chciałem tylko powiedzieć, że po latach spędzonych na przepełnieniu stosów, myślę, że może to być jedna z najlepszych odpowiedzi, jakie kiedykolwiek spotkałem. Świetny przykład i wyjaśnienie Dziękuję.
user3344977
Wszedłem tutaj, spodziewając się uzyskać więcej informacji, coś w rodzaju TLDR tego raw.githubusercontent.com/git/git/master/Documentation/howto/ ...
wviana
1
@wviana Jeśli znalezione informacje są niewystarczające, napisz odpowiedź. Zwróć uwagę, że przepełnienie stosu nie zastąpi oficjalnej dokumentacji (do której wydajesz się odnosić i obejmuje znacznie szerszy zakres niż to pytanie).
AD7six
35

Użyj Git Revert w ten sposób:

git revert <insert bad commit hash here>

git revert tworzy nowe zatwierdzenie ze zmianami, które są wycofywane. git resetusuwa historię git zamiast tworzyć nowe zatwierdzenie.

Kolejne kroki są takie same, jak w przypadku każdego innego zatwierdzenia.

Johnny Z
źródło
Różnica między „przywróć zatwierdzenie” i „przywróć zatwierdzenie” jest na tyle subtelna, że ​​zmagałem się z tym poleceniem przez lata. Twoje wyjaśnienie rozwiązało to dla mnie natychmiast. Dzięki!
claviska
24

Powód resetirevert często pojawia się w tych samych rozmowach jest to, że różne systemy kontroli wersji używają ich do oznaczania różnych rzeczy.

W szczególności ludzie, którzy są przyzwyczajeni do SVN lub P4, którzy chcą wyrzucić niezatwierdzone zmiany w pliku, często sięgają, revertzanim powiedzą im, że naprawdę chcąreset .

Podobnie, revertodpowiednik w innych VCS jest często nazywany rollbacklub czymś podobnym - ale „wycofanie” może również oznaczać „Chcę całkowicie odrzucić kilka ostatnich zatwierdzeń”, co jest odpowiednie, resetale nie revert. Jest więc wiele nieporozumień, gdy ludzie wiedzą, co chcą zrobić, ale nie są jasne, którego polecenia powinni użyć.

Jeśli chodzi o twoje rzeczywiste pytania dotyczące przywracania ...

OK, zamierzasz użyć Git Revert, ale jak?

git revert first-bad-commit..last-bad-commit

A po uruchomieniu git revert musisz zrobić coś innego? Czy musisz zatwierdzić zmiany, cofnąć wprowadzone zmiany, czy przywrócić bezpośrednie zobowiązanie do repozytorium, czy co?

Domyślnie git revertpyta o komunikat zatwierdzenia, a następnie zatwierdza wyniki. Można to zmienić. Cytuję stronę podręcznika :

--edytować

Z tą opcją, git revert pozwoli ci edytować komunikat zatwierdzenia przed zatwierdzeniem przywrócenia. Jest to ustawienie domyślne, jeśli uruchamiasz polecenie z terminala.

--no-commit

Zwykle polecenie automatycznie tworzy niektóre zatwierdzenia z komunikatami dziennika zatwierdzeń określającymi, które zatwierdzenia zostały cofnięte. Ta flaga powoduje zastosowanie zmian niezbędnych do przywrócenia nazwanych zatwierdzeń do twojego drzewa roboczego i indeksu, ale nie wprowadza zmian. Ponadto, gdy używana jest ta opcja, twój indeks nie musi pasować do zatwierdzenia HEAD. Przywrócenie jest wykonywane względem początkowego stanu indeksu.

Jest to przydatne podczas przywracania więcej niż jednego efektu zatwierdzeń do indeksu z rzędu.

W szczególności, domyślnie tworzy nowe zatwierdzenie dla każdego przywracanego zatwierdzenia. Możesz użyć revert --no-commitdo tworzenia zmian, które przywracają je wszystkie bez zatwierdzania tych zmian jako indywidualnych zatwierdzeń, a następnie zatwierdzaj w wolnym czasie.

ToxicFrog
źródło
git revert first-bad-commit..last-bad-commit: Myślę, że tak powinno być git revert parent-of-first-bad-commit..last-bad-commit.
user1071847
10

Pytanie jest dość stare, ale powrót wciąż dezorientuje ludzi (takich jak ja)

Jako początkujący, po kilku próbach i błędach (więcej błędów niż prób) mam ważny punkt:

  • git revertwymaga identyfikatora zatwierdzenia, które chcesz usunąć, zachowując go w historii

  • git resetwymaga zatwierdzenia, które chcesz zachować , i w konsekwencji usunie wszystko później z historii.

Oznacza to, że jeśli użyjesz revertz pierwszym identyfikatorem zatwierdzenia, znajdziesz się w pustym katalogu i dodatkowym zatwierdzeniu w historii, podczas gdy przy resetowaniu katalog zostanie ... przywrócony do początkowego zatwierdzenia, a historia będzie wyglądać tak, jakby ostatnie zatwierdzenie (a) nigdy się nie wydarzyło.

Aby być jeszcze bardziej przejrzystym, z takim dziennikiem:

# git log --oneline

cb76ee4 wrong
01b56c6 test
2e407ce first commit

Użycie git revert cb76ee4will domyślnie przeniesie twoje pliki z powrotem do 01b56c6 i doda kolejne zatwierdzenie do twojej historii:

8d4406b Revert "wrong"
cb76ee4 wrong
01b56c6 test
2e407ce first commit

git reset 01b56c6 zamiast tego przeniesie twoje pliki z powrotem do 01b56c6 i wyczyści każde inne zatwierdzenie po tym z twojej historii:

01b56c6 test
2e407ce first commit

Wiem, że to „podstawa”, ale było to dla mnie dość mylące, ponieważ działając revertna pierwszym id („pierwsze zatwierdzenie”) spodziewałem się znaleźć moje początkowe pliki, zajęło trochę czasu zanim zrozumiałem, że jeśli potrzebujesz swoich plików z powrotem jako „pierwsze zatwierdzenie” musisz użyć następnego id.

bzdury
źródło
Zaobserwowałem to samo. jego naprawdę zagmatwane, ale tak ważne, aby wiedzieć. niedawno musiałem pomóc współpracownikowi i zapomniałem o tym. To było trochę zawstydzające.
ExOfDe
1

Cofnąłem kilka zatwierdzeń, uruchamiając polecenie „git revert commit id”, na przykład:

git revert b2cb7c248d416409f8eb42b561cbff91b0601712

Następnie zostałem poproszony o zatwierdzenie przywrócenia (tak jak w przypadku uruchomienia polecenia „git commit”). Mój domyślny program terminalowy to Vim, więc uruchomiłem:

:wq 

W końcu wprowadziłem zmianę do repozytorium za pomocą:

git push
jrc16
źródło