Close

Resetting, checking out & reverting


The git reset, git checkout, and git revert commands are some of the most useful tools in your Git toolbox. They all let you undo some kind of change in your repository, and the first two commands can be used to manipulate either commits or individual files.

Ponieważ są tak do siebie podobne, bardzo łatwo jest zapomnieć, które polecenie należy zastosować w danym przypadku. W tym artykule porównamy najpopularniejsze konfiguracje git reset, git checkout i git revert. Mamy nadzieję, że po przeczytaniu tego tekstu nabierzesz pewności siebie w poruszaniu się po repozytorium za pomocą każdego z tych poleceń.

Trzy drzewa Git

It helps to think about each command in terms of their effect on the three state management mechanisms of a Git repository: the working directory, the staged snapshot, and the commit history. These components are sometimes known as "The three trees" of Git. We explore the three trees in depth on the git reset page. Keep these mechanisms in mind as you read through this article.

Wyewidencjonowanie to operacja, która przesuwa wskaźnik odnośnika HEAD do określonego commitu. Aby to zademonstrować, rozważmy następujący przykład.

Przesunięcie wskaźnika HEAD do określonego commitu
Bazy danych
materiały pokrewne

Jak przenieść pełne repozytorium Git

Logo Bitbucket
POZNAJ ROZWIĄZANIE

Poznaj środowisko Git z rozwiązaniem Bitbucket Cloud

Powyższy przykład przedstawia sekwencję commitów na gałęzi main. Odwołania HEAD i main wskazują obecnie na commit d. Wykonajmy teraz polecenie git checkout b.

Sequence of commits on the main branch

Na ilustracji widzimy aktualizację drzewa „historii commitów”. Polecenie git checkout można zastosować na poziomie commitu lub na poziomie pliku. Wyewidencjonowanie na poziomie pliku zmieni jego zawartość na zawartość określonego commitu.

Przywrócenie to operacja, która powoduje pobranie określonego commitu i utworzenie nowego, odwracającego ten poprzedni. Polecenie git revert można uruchamiać tylko w zakresie poziomu commitu i nie obejmuje funkcjonalności poziomu pliku.

Resetowanie to operacja, która powoduje przywrócenie „trzech drzew” do takiego stanu, aby pasowały do repozytorium dla określonego commitu. Reset można wywołać w trzech różnych trybach, które odpowiadają poszczególnym drzewom.

Wyewidencjonowanie i reset zwykle używa się do dokonywania lokalnych lub prywatnych „cofnięć”. Modyfikują historię repozytorium, co może powodować konflikty podczas przepychania do zdalnych repozytoriów współdzielonych. Przywrócenie uznaje się za bezpieczniejsze rozwiązanie do „cofnięć publicznych”, ponieważ tworzy nową historię, która może być udostępniana zdalnie i nie nadpisuje dotychczasowej, od której mogą być zależni zdalni członkowie zespołu.

Git reset vs revert vs checkout reference


Poniższa tabela stanowi podsumowanie najczęstszych przypadków użycia każdego z tych poleceń. Warto zawsze ją mieć pod ręką, ponieważ może się nieraz przydać podczas używania systemu Git.

Polecenie

Zakres

Popularne przykłady zastosowania

git reset

Zakres

Poziom commitu

Popularne przykłady zastosowania

Discard commits in a private branch or throw away uncommitted changes

git reset

Zakres

Poziom pliku

Popularne przykłady zastosowania

Wycofanie pliku z przechowalni

git checkout

Zakres

Poziom commitu

Popularne przykłady zastosowania

Przełączanie między gałęziami lub przeglądanie starszych migawek

git checkout

Zakres

Poziom pliku

Popularne przykłady zastosowania

Odrzucenie zmian w katalogu roboczym

git revert

Zakres

Poziom commitu

Popularne przykłady zastosowania

Cofnięcie commitów w gałęzi publicznej

git revert

Zakres

Poziom pliku

Popularne przykłady zastosowania

(nie dotyczy)

Commit level operations


Parametry, które przekazujesz do poleceń git reset i git checkout, określają ich zakres. Jeśli nie uwzględnisz ścieżki pliku jako parametru, operują na całych commitach. To właśnie będziemy omawiać w tej sekcji. Zauważ, że polecenie git revert nie ma odpowiednika na poziomie pliku.

Reset a specific commit

Na poziomie commitu resetowanie służy do przesunięcia końcówki gałęzi do innego commitu. Można to wykorzystać do usunięcia commitów z bieżącej gałęzi. Na przykład poniższe polecenie przesuwa gałąź hotfix do tyłu o dwa commity.

git checkout hotfix git reset HEAD~2

Dwa commity, które znajdowały się na końcu gałęzi hotfix, to teraz commity „zwisające” lub „osierocone”. Oznacza to, że zostaną usunięte następnym razem, gdy Git wykona procedurę eliminacji zbędnych elementów. Innymi słowy zaznaczasz, że chcesz się pozbyć tych commitów. Można to zwizualizować w następujący sposób:

Resetowanie gałęzi hotfix do HEAD-2

Ten sposób użycia git reset stanowi prostą metodę cofnięcia zmian, które nie zostały jeszcze udostępnione nikomu innemu. To przydatne polecenie na wypadek, gdy zaczniesz pracować nad funkcją, ale nagle pomyślisz „O kurczę, co ja robię? Muszę zacząć od nowa”.

Oprócz przeniesienia bieżącej gałęzi możesz również użyć git reset do modyfikacji migawki w przechowalni i/lub katalogu roboczego przez przekazanie jednej z następujących flag:

  • --soft — migawka w przechowalni i katalog roboczy nie zostają zmienione w żaden sposób.
  • —mixed — migawka w przechowalni zostaje aktualizowana tak, aby pasowała do określonego commitu, ale katalog roboczy nie ulega zmianie. To jest opcja domyślna.
  • —hard — migawka w przechowalni i katalog roboczy zostają aktualizowane tak, aby pasowały do określonego commitu.

It’s easier to think of these modes as defining the scope of a git reset operation. For further detailed information visit the git reset page.

Wyewidencjonowanie starych commitów

Polecenie git checkout służy do aktualizacji stanu repozytorium do określonego punktu w historii projektu. W przypadku przekazania z nazwą gałęzi umożliwia przełączanie się między gałęziami.

git checkout hotfix

Wewnętrznie, jedynym efektem powyższego polecenia jest przeniesienie wskaźnika HEAD do innej gałęzi i uaktualnienie katalogu roboczego, aby do niej pasował. Ponieważ może to spowodować nadpisanie lokalnych zmian, system Git wymusza na użytkowniku zatwierdzenie lub dodanie do schowka zmian w katalogu roboczym, które zostaną utracone podczas operacji wyewidencjonowania. W przeciwieństwie do git reset polecenie git checkout nie przenosi gałęzi.

Moving HEAD from main to hotfix

Możesz także wyewidencjonować dowolne commity przez przekazanie odniesień do commitów zamiast gałęzi. Daje to ten sam efekt co wyewidencjonowanie gałęzi: przenosi odniesienie HEAD do określonego commitu. Na przykład następujące polecenie spowoduje wyewidencjonowanie elementu nadrzędnego w drugim stopniu względem bieżącego commitu:

git checkout HEAD~2
Przenoszenie HEAD do dowolnie wybranego commitu

Przydaje się to do uzyskania szybkiego podglądu starszej wersji projektu. Ponieważ nie ma jednak odniesienia gałęzi do bieżącego wskaźnika HEAD, to powoduje ustawienie w stanie odłączonego wskaźnika HEAD. Może to być problematyczne w przypadku dodawania nowych commitów, ponieważ nie będzie możliwości powrotu do nich po przejściu na inną gałąź. Z tego względu przed dodaniem commitów do odłączonego wskaźnika HEAD zawsze należy utworzyć nową gałąź.

Undo public commits with revert

Przywrócenie powoduje cofnięcie commitu przez utworzenie nowego commitu. To bezpieczny sposób cofania zmian, ponieważ nie grozi nadpisaniem historii commitów. Na przykład poniższe polecenie spowoduje wyszukanie zmian zawartych w przedostatnim commicie, utworzenie nowego commitu cofającego te zmiany oraz dołączenie nowego commitu do istniejącego projektu.

git checkout hotfix git revert HEAD~2

Można to zwizualizować w następujący sposób:

Przywracanie do przedostatniego commitu

Porównaj to z poleceniem git reset, które zmienia istniejącą historię commitów. Z tego względu do cofania zmian w gałęzi publicznej należy używać polecenia git revert, zaś git reset powinno służyć wyłącznie do cofania zmian w gałęzi prywatnej.

Można powiedzieć, że git revert to narzędzie do cofania zatwierdzonych zmian, podczas gdy git reset HEAD służy do cofania zmian niezatwierdzonych.

Tak samo jak git checkout polecenie git revert może nadpisać pliki w katalogu roboczym, dlatego poprosi o zatwierdzenie lub dodanie do schowka zmian, które mogłyby zostać utracone podczas operacji przywracania.

File-level operations


Polecenia git reset i git checkout również dopuszczają opcjonalną ścieżkę pliku jako parametr. To znacząco zmienia ich działanie. Zamiast działać na całych migawkach, zostają zmuszone do ograniczenia zakresu do pojedynczego pliku.

Git reset a specific file

Po wywołaniu ze ścieżką pliku polecenie git reset aktualizuje migawkę w przechowalni tak, aby pasowała do wersji z określonego commitu. Na przykład polecenie to powoduje pobranie wersji foo.py w przedostatnim commicie i jej przeniesienie do przechowalni na potrzeby następnego commitu:

git reset HEAD~2 foo.py

Podobnie jak w przypadku git reset na poziomie commitu rozwiązanie to częściej stosuje się względem wskaźnika HEAD niż dowolnie wybranego commitu. Uruchomienie polecenia git reset HEAD foo.py spowoduje cofnięcie pliku foo.py z przechowalni. Zawarte w nim zmiany będą nadal obecne w katalogu roboczym.

Przenoszenie pliku z historii commitów do migawki w przechowalni

Flagi --soft, --mixed i --hard nie mają wpływu na git reset na poziomie plików, ponieważ migawka w przechowalni jest zawsze aktualizowana, a katalog roboczy nigdy nie jest aktualizowany.

Git checkout file

Wyewidencjonowanie pliku przypomina użycie polecenia git reset ze ścieżką pliku, z tym, że aktualizuje katalog roboczy zamiast przechowalni. W przeciwieństwie do polecenia na poziomie commitu nie powoduje to przesunięcia odniesienia HEAD, więc nie będzie możliwe przełączanie między gałęziami.

Przenoszenie pliku z historii commitów do katalogu roboczego

Na przykład poniższe polecenie powoduje dopasowanie pliku foo.py w katalogu roboczym do tego z przedostatniego commitu:

git checkout HEAD~2 foo.py

Podobnie jak wywołanie git checkout na poziomie commitu może to być używane do sprawdzania starszych wersji projektu — zakres ograniczony jest jednak do określonego pliku.

Gdy przenosisz do przechowalni i zatwierdzasz wyewidencjonowany plik, daje to efekt „przywrócenia” jego starszej wersji. Oznacza to usunięcie wszystkich kolejnych zmian w pliku, podczas gdy polecenie git revert cofa wyłącznie zmiany wprowadzone przez określony commit.

Podobnie jak git reset polecenie to jest powszechnie używane wraz ze wskaźnikiem HEAD jako odniesienie do commitu. Na przykład polecenie git checkout HEAD foo.py powoduje odrzucenie zmian spoza przechowalni w pliku foo.py. Jest to zachowanie podobne, jak w przypadku polecenia git reset HEAD --hard, ale dotyczy tylko określonego pliku.

Podsumowanie


You should now have all the tools you could ever need to undo changes in a Git repository. The git reset, git checkout, and git revert commands can be confusing, but when you think about their effects on the working directory, staged snapshot, and commit history, it should be easier to discern which command fits the development task at hand.


Udostępnij ten artykuł

Zalecane lektury

Dodaj te zasoby do zakładek, aby dowiedzieć się więcej na temat rodzajów zespołów DevOps lub otrzymywać aktualności na temat metodyki DevOps w Atlassian.

Ludzie współpracujący przy ścianie pełnej narzędzi

Blog Bitbucket

Ilustracja DevOps

Ścieżka szkoleniowa DevOps

Demonstracje funkcji z ekspertami Atlassian

Zobacz, jak Bitbucket Cloud współpracuje z Atlassian Open DevOps

Zapisz się do newslettera DevOps

Thank you for signing up