Ogólnie rzecz biorąc, git reset
funkcja polega na pobraniu bieżącej gałęzi i zresetowaniu jej, aby wskazywała gdzieś indziej, i ewentualnie zabraniu ze sobą indeksu i drzewa roboczego. Mówiąc konkretniej, jeśli twoja główna gałąź (obecnie wypisana) wygląda następująco:
- A - B - C (HEAD, master)
i zdajesz sobie sprawę, że chcesz, aby mistrz wskazywał na B, a nie na C, użyjesz git reset B
go tam:
- A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore
Dygresja: różni się od kasy. Gdybyś biegł git checkout B
, dostałbyś to:
- A - B (HEAD) - C (master)
Skończyło się na odłączeniu HEAD. HEAD
, drzewo pracy, indeksuj wszystkie pasujące B
, ale gałąź master pozostała w miejscu C
. Jeśli dokonasz nowego zatwierdzenia D
w tym momencie, otrzymasz to, co prawdopodobnie nie jest tym, czego chcesz:
- A - B - C (master)
\
D (HEAD)
Pamiętaj, że reset nie dokonuje zatwierdzeń, po prostu aktualizuje gałąź (która jest wskaźnikiem zatwierdzenia), aby wskazać inne zatwierdzenie. Reszta to tylko szczegóły tego, co dzieje się z twoim indeksem i drzewem pracy.
Przypadków użycia
Omawiam wiele głównych przypadków użycia w git reset
ramach moich opisów różnych opcji w następnej sekcji. Można go naprawdę używać do wielu różnych rzeczy; wspólny wątek polega na tym, że wszystkie wymagają resetowania gałęzi, indeksu i / lub drzewa roboczego, aby wskazać / dopasować dane zatwierdzenie.
Rzeczy, na które należy uważać
--hard
może spowodować, że naprawdę stracisz pracę. Zmienia twoje drzewo pracy.
git reset [options] commit
może powodować (poniekąd) utratę zatwierdzeń. W powyższym przykładzie zabawki straciliśmy zatwierdzenie C
. Nadal jest w repozytorium i można go znaleźć, patrząc na git reflog show HEAD
lub git reflog show master
, ale w rzeczywistości nie jest już dostępny z żadnej gałęzi.
Git trwale usuwa takie zatwierdzenia po 30 dniach, ale do tego czasu możesz odzyskać C, ponownie wskazując na niego gałąź ( git checkout C; git branch <new branch name>
).
Argumenty
Parafrazując stronę podręcznika, najczęstszym zastosowaniem jest forma git reset [<commit>] [paths...]
, która zresetuje podane ścieżki do ich stanu z podanego zatwierdzenia. Jeśli ścieżki nie zostaną podane, całe drzewo zostanie zresetowane, a jeśli zatwierdzenie nie zostanie podane, zostanie uznane za HEAD (bieżące zatwierdzenie). Jest to powszechny wzór w poleceniach git (np. Checkout, diff, log, choć dokładna semantyka jest różna), więc nie powinno być zbyt zaskakujące.
Na przykład git reset other-branch path/to/foo
resetuje wszystko w ścieżce / do / foo do stanu w innej gałęzi, git reset -- .
resetuje bieżący katalog do stanu w HEAD, a prosty git reset
resetuje wszystko do stanu w HEAD.
Główne drzewo pracy i opcje indeksu
Istnieją cztery główne opcje kontrolowania tego, co dzieje się z drzewem pracy i indeksem podczas resetowania.
Pamiętaj, że indeks jest „obszarem przejściowym” gita - tam gdzie idą rzeczy, kiedy mówisz git add
w ramach przygotowań do zatwierdzenia.
--hard
dopasowuje wszystko do zatwierdzonego resetu. Prawdopodobnie jest to najłatwiejszy do zrozumienia. Wszystkie lokalne zmiany zostaną zablokowane. Jednym z podstawowych zastosowań jest zdmuchnięcie twojej pracy, ale nie zmiana zatwierdzeń: git reset --hard
oznacza git reset --hard HEAD
, tzn. Nie zmieniaj gałęzi, ale pozbądź się wszystkich lokalnych zmian. Drugim jest po prostu przenoszenie gałęzi z jednego miejsca do drugiego i utrzymywanie synchronizacji drzewa indeksu / pracy. Jest to ten, który może naprawdę spowodować utratę pracy, ponieważ modyfikuje twoje drzewo pracy. Bądź bardzo pewny, że chcesz odrzucić pracę lokalną, zanim ją uruchomisz reset --hard
.
--mixed
jest wartością domyślną, tj . git reset
oznacza git reset --mixed
. Resetuje indeks, ale nie drzewo robocze. Oznacza to, że wszystkie twoje pliki są nienaruszone, ale wszelkie różnice między oryginalnym zatwierdzeniem a tym, którego zresetowałeś, pojawią się jako lokalne modyfikacje (lub nieśledzone pliki) ze statusem git. Użyj tego, gdy zdasz sobie sprawę, że popełniłeś złe błędy, ale chcesz zachować całą pracę, którą wykonałeś, aby to naprawić i ponownie uruchomić. Aby zatwierdzić, musisz ponownie dodać pliki do indeksu ( git add ...
).
--soft
nie dotyka indeksu ani drzewa pracy. Wszystkie twoje pliki są nienaruszone jak przy --mixed
, ale wszystkie zmiany pokazują się jak changes to be committed
przy statusie git (tj. Sprawdzone w przygotowaniu do zatwierdzenia). Użyj tego, gdy zdasz sobie sprawę, że popełniłeś złe błędy, ale praca jest dobra - wszystko, co musisz zrobić, to ponownie ją uruchomić. Indeks jest nietknięty, więc możesz zatwierdzić natychmiast, jeśli chcesz - wynikowe zatwierdzenie będzie miało taką samą treść, jak w miejscu, w którym byłeś przed zresetowaniem.
--merge
został dodany niedawno i ma na celu pomóc w przerwaniu nieudanego scalenia. Jest to konieczne, ponieważ git merge
faktycznie pozwoli ci podjąć próbę scalenia z brudnym drzewem roboczym (jednym z lokalnymi modyfikacjami), o ile modyfikacje te znajdują się w plikach, na które nie ma wpływu scalanie. git reset --merge
resetuje indeks (jak --mixed
- wszystkie zmiany są wyświetlane jako modyfikacje lokalne) i resetuje pliki, na które wpływa scalanie, ale pozostawia inne w spokoju. Miejmy nadzieję, że przywróci to wszystko tak, jak było przed złym połączeniem. Zazwyczaj używasz go jako git reset --merge
(znaczącego git reset --merge HEAD
), ponieważ chcesz tylko zresetować scalenie, a nie przesunąć gałąź. ( HEAD
nie został jeszcze zaktualizowany, ponieważ scalenie nie powiodło się)
Aby być bardziej konkretnym, załóżmy, że zmodyfikowałeś pliki A i B i próbujesz scalić w gałęzi, która zmodyfikowała pliki C i D. Scalanie z jakiegoś powodu kończy się niepowodzeniem i decydujesz się go przerwać. Ty używasz git reset --merge
. Powoduje, że C i D wracają do tego, jak były HEAD
, ale pozostawia twoje modyfikacje w A i B w spokoju, ponieważ nie były one częścią próby scalenia.
Chcieć wiedzieć więcej?
Sądzę, że man git reset
jest to całkiem dobre - być może potrzebujesz trochę sposobu, w jaki działa git, aby naprawdę się zagłębili. W szczególności, jeśli poświęcisz trochę czasu na ich uważne przeczytanie, bardzo pomocne są te tabele przedstawiające stany plików w indeksie i drzewie pracy dla wszystkich różnych opcji i przypadków. (Ale tak, są bardzo gęste - przekazują bardzo dużo powyższych informacji w bardzo zwięzłej formie).
Dziwna notacja
„Dziwny zapis” ( HEAD^
i HEAD~1
), o którym wspominasz, jest po prostu skrótem do określania zatwierdzeń, bez konieczności używania nazwy skrótu takiej jak 3ebe3f6
. Jest to w pełni udokumentowane w sekcji „określanie wersji” strony podręcznika dla git-rev-pars, z dużą ilością przykładów i powiązanej składni. Karetka i tylda faktycznie oznaczają różne rzeczy :
HEAD~
jest skrótem od HEAD~1
i oznacza pierwszego rodzica zatwierdzenia. HEAD~2
oznacza pierwszego rodzica pierwszego zatwierdzenia. Pomyśl o tym, HEAD~n
jak „n zobowiązuje się przed HEAD” lub „przodek HEAD n-tej generacji”.
HEAD^
(lub HEAD^1
) oznacza również pierwszego rodzica zatwierdzenia. HEAD^2
oznacza drugiego rodzica zatwierdzenia . Pamiętaj, że normalne zatwierdzenie scalania ma dwoje rodziców - pierwszym rodzicem jest zatwierdzone scalenie, a drugim rodzicem jest scalone zatwierdzenie. Zasadniczo połączenia mogą mieć dowolnie wielu rodziców (połączenia ośmiornic).
- Te
^
i ~
operatorzy mogą być połączone razem, tak jak w HEAD~3^2
, drugi macierzysty przodka trzeciej generacji HEAD
, HEAD^^2
, drugi macierzysty pierwszego rodzica HEAD
lub nawet HEAD^^^
, co jest równoważne HEAD~3
.