Ogólnie rzecz biorąc, git resetfunkcja 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 Bgo 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 Dw 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 resetramach 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ć
--hardmoże spowodować, że naprawdę stracisz pracę. Zmienia twoje drzewo pracy.
git reset [options] commitmoż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 HEADlub 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/fooresetuje 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 resetresetuje 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 addw ramach przygotowań do zatwierdzenia.
--harddopasowuje 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 --hardoznacza 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.
--mixedjest wartością domyślną, tj . git resetoznacza 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 ...).
--softnie dotyka indeksu ani drzewa pracy. Wszystkie twoje pliki są nienaruszone jak przy --mixed, ale wszystkie zmiany pokazują się jak changes to be committedprzy 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.
--mergezostał dodany niedawno i ma na celu pomóc w przerwaniu nieudanego scalenia. Jest to konieczne, ponieważ git mergefaktycznie 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 --mergeresetuje 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łąź. ( HEADnie 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 resetjest 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~1i oznacza pierwszego rodzica zatwierdzenia. HEAD~2oznacza pierwszego rodzica pierwszego zatwierdzenia. Pomyśl o tym, HEAD~njak „n zobowiązuje się przed HEAD” lub „przodek HEAD n-tej generacji”.
HEAD^(lub HEAD^1) oznacza również pierwszego rodzica zatwierdzenia. HEAD^2oznacza 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 HEADlub nawet HEAD^^^, co jest równoważne HEAD~3.
