git revert
Polecenie git revert
można uznać za polecenie cofania, jednak jego działanie różni się trochę od tradycyjnej operacji cofania. Nie powoduje usunięcia commita z historii projektu, tylko analizuje sposób, w jaki odwrócić zmiany w commicie, a następnie dołącza nowy commit z odwrotnością zmian. Dzięki temu w systemie Git nie dochodzi do utraty historii, co jest ważne w celu zapewnienia integralności historii rewizji i niezawodnej współpracy.
Odwracania należy używać, gdy chcesz zastosować odwrotność commita z historii projektu. Może to być przydatne, na przykład gdy szukasz błędu i odkrywasz, że został wprowadzony przez pojedynczy commit. Zamiast ręcznie naprawiać i zatwierdzać nową migawkę możesz użyć polecenia git revert
, aby te wszystkie działania zostały automatycznie wykonane za Ciebie.
Jak to działa
Polecenie git revert
służy do cofania zmian w historii commitów repozytorium. Pozostałe polecenia cofania, takie jak git checkout
i git reset
, przenoszą wskaźnik HEAD
i wskaźniki odniesień do gałęzi do określonego commita. Git revert
również przyjmuje określone zatwierdzenie, jednak git revert
nie przenosi wskaźników odniesienia do tego zatwierdzenia. Operacja cofania odwróci zmiany z określonego commita i w ten sposób utworzy nowy commit. Wskaźniki odniesienia są następnie aktualizowane, aby wskazywały nowy, odwrócony commit, co czyni go końcówką gałęzi.
Aby to zademonstrować, utwórzmy przykładowe repozytorium za pomocą poniższych poleceń:
$ mkdir git_revert_test
$ cd git_revert_test/
$ git init .
Initialized empty Git repository in /git_revert_test/.git/
$ touch demo_file
$ git add demo_file
$ git commit -am"initial commit"
[main (root-commit) 299b15f] initial commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 demo_file
$ echo "initial content" >> demo_file
$ git commit -am"add new content to demo file"
[main 3602d88] add new content to demo file
n 1 file changed, 1 insertion(+)
$ echo "prepended line content" >> demo_file
$ git commit -am"prepend content to demo file"
[main 86bb32e] prepend content to demo file
1 file changed, 1 insertion(+)
$ git log --oneline
86bb32e prepend content to demo file
3602d88 add new content to demo file
299b15f initial commit
Zainicjowaliśmy repozytorium w nowo utworzonym katalogu o nazwie git_revert_test
. Dodaliśmy 3 commity do repozytorium, w którym dodaliśmy plik demo_file
i dwukrotnie zmodyfikowaliśmy jego zawartość. Na koniec procedury konfiguracji repozytorium wywołujemy polecenie git log
, aby wyświetlić historię zatwierdzeń, która zawiera łącznie 3 commity. Ten stan repozytorium umożliwia wykonanie polecenia git revert
.
$ git revert HEAD
[main b9cd081] Revert "prepend content to demo file" 1 file changed, 1 deletion(-)
Polecenie git revert
oczekuje przekazania odniesienia do commita i nie zostanie wykonane bez niego. Tutaj przekazaliśmy odniesienie w postaci wskaźnika HEAD
. Spowoduje to cofnięcie ostatniego zatwierdzenia. Jest to takie samo zachowanie, jak przywrócenie commita 3602d8815dbfa78cd37cd4d189552764b5e96c58
. Podobnie jak w przypadku scalania, przywrócenie utworzy nowe zatwierdzenie, które otworzy skonfigurowany edytor systemowy z prośbą o nowy komunikat dotyczący commita. Po wprowadzeniu i zapisaniu komunikatu dotyczącego commita Git wznowi działanie. Możemy teraz sprawdzić stan repozytorium za pomocą git log
i zobaczyć, że do poprzedniego dziennika dodano nowy commit:
$ git log --oneline 1061e79 Revert "prepend content to demo file" 86bb32e prepend content to demo file 3602d88 add new content to demo file 299b15f initial commit
Zwróć uwagę, że trzeci commit jest nadal widoczny w historii projektu po przywróceniu. Zamiast go usuwać, polecenie git revert
dodało nowe zatwierdzenie, aby cofnąć jego zmiany. W rezultacie drugi i czwarty commit reprezentują dokładnie tę samą bazę kodu, a trzecie zatwierdzenie jest nadal w naszej historii na wypadek, gdybyśmy chcieli wrócić do niego w przyszłości.
Często używane opcje
-e
--edit
Jest to opcja domyślna i nie trzeba jej określać. Ta opcja otworzy skonfigurowany edytor systemowy i wyświetli monit o edycję komunikatu dotyczącego commita przed zatwierdzeniem cofnięcia.
--no-edit
Jest to odwrotność opcji -e
. Przywrócenie nie spowoduje otwarcia edytora.
-n
--no-commit
Przekazanie tej opcji uniemożliwi poleceniu git revert
utworzenie nowego commita, który odwróci docelowe zatwierdzenie. Zamiast tworzenia nowego zatwierdzenia ta opcja doda odwrotność zmian do indeksu staging i katalogu roboczego. Są to inne drzewa używane przez Git do zarządzania statusem repozytorium. Aby uzyskać więcej informacji, odwiedź stronę git reset
.
Porównanie resetowania i przywracania
Ważne jest, aby zrozumieć, że git revert
cofa pojedynczy commit — nie „przywraca” poprzedniego stanu projektu poprzez usunięcie wszystkich kolejnych commitów. W Git nazywa się to resetowaniem, a nie przywracaniem.
Przywracanie ma dwie ważne zalety w porównaniu z resetowaniem. Po pierwsze, nie zmienia historii projektu, co czyni go „bezpieczną” operacją dla commitów, które już opublikowano w udostępnionym repozytorium. Szczegółowe informacje na temat tego, dlaczego zmiana historii udostępnionej jest niebezpieczna, zawiera strona poświęcona poleceniu git reset.
Po drugie, polecenie git revert
może odwoływać się do indywidualnego commita w dowolnym punkcie historii, podczas gdy git reset
może działać tylko wstecz od bieżącego commita. Na przykład, jeśli chcesz wycofać stary commit za pomocą polecenia git reset
, musisz usunąć wszystkie commity, które wystąpiły po commicie docelowym, usunąć go, a następnie ponownie dodać wszystkie kolejne commity. Nie trzeba dodawać, że nie jest to zbyt eleganckie rozwiązanie cofania. Bardziej szczegółowe omówienie różnic między git revert
a innymi poleceniami cofania zawiera artykuł Resetowanie, wyewidencjonowywanie i cofanie.
Podsumowanie
Polecenie git revert
jest operacją cofania do przodu, która oferuje bezpieczną metodę cofania zmian. Zamiast usuwać lub osieracać commity w historii zatwierdzania przywracanie utworzy nowe zatwierdzenie, które odwróci określone zmiany. Git revert
jest bezpieczniejszą alternatywą dla git reset
w odniesieniu do utraty dodanego kodu. Aby zademonstrować efekty git revert
, wykorzystaliśmy inne polecenia, które mają bardziej szczegółową dokumentację na swoich stronach: git log
, git commiti
git reset.