Po angielsku, co robi "Git reset"?

Widziałem ciekawe posty wyjaśniające subtelności o git reset.

Niestety, im więcej o tym czytam, tym bardziej wydaje się, że nie do końca to Rozumiem. Pochodzę z środowiska SVN i Git jest zupełnie nowym paradygmatem. Łatwo dostałem mercurial, ale Git jest znacznie bardziej techniczny.

Myślę, że {[0] } jest blisko hg revert, ale wydaje się, że są różnice.

Więc co dokładnie robi git reset? Prosimy o szczegółowe wyjaśnienia o:

  • Opcje --hard, --soft i --merge;
  • dziwny zapis, którego używasz z HEAD, taki jak HEAD^ i HEAD~1;
  • konkretne przypadki użycia i przepływy pracy;
  • konsekwencje dla kopii roboczej, HEAD i Twojego globalnego poziomu stresu.
 693
Author: Mus, 2010-03-27

7 answers

Ogólnie rzecz biorąc, funkcja git reset polega na przeniesieniu bieżącej gałęzi i zresetowaniu jej, aby wskazywała gdzie indziej, i ewentualnie przybliżyć indeks i drzewo robocze. Bardziej konkretnie, jeśli twoja gałąź master (aktualnie sprawdzona) wygląda tak:

- A - B - C (HEAD, master)

I zdajesz sobie sprawę, że chcesz, aby master wskazywał na B, a nie C, użyjesz git reset B, aby przenieść go tam: {]}

- A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore

Dygresja: to różni się od kasy. Jeśli biegniesz git checkout B, dostaniesz to:

- A - B (HEAD) - C (master)

Skończyłeś w oderwanym Stan głowy. HEAD, drzewo pracy, indeks all match B, ale gałąź master została pozostawiona na C. Jeśli w tym momencie utworzysz nowy commit D, dostaniesz to, co prawdopodobnie nie jest tym, czego chcesz:

- A - B - C (master)
       \
        D (HEAD)

Pamiętaj, że reset NIE tworzy commitów, tylko aktualizuje gałąź (która jest wskaźnikiem do commita), aby wskazać inny commit. Reszta to tylko szczegóły tego, co dzieje się z Twoim indeksem i drzewem roboczym.

Przypadki użycia

I obejmuje wiele głównych przypadków użycia dla git reset w moich opisach różnych opcji w następnej sekcji. W rzeczywistości może być używany do wielu różnych rzeczy; wspólnym wątkiem jest to, że wszystkie z nich wymagają zresetowania gałęzi, indeksu i/lub drzewa pracy, aby wskazać/dopasować dany commit.

Things to be careful of

  • --hard może spowodować, że naprawdę stracisz pracę. Modyfikuje Twoje drzewko pracy.

  • git reset [options] commit może spowodować (w pewnym sensie) utratę commitów. W powyższym przykładzie straciliśmy commit C. Jest nadal w repo i możesz go znaleźć patrząc na git reflog show HEAD lub git reflog show master, ale nie jest już dostępny z żadnej gałęzi.

  • Git trwale usuwa takie commity po 30 dniach, ale do tego czasu możesz odzyskać C, wskazując gałąź na niego ponownie (git checkout C; git branch <new branch name>).

Argumenty

Parafrazując stronę podręcznika, najczęściej używa się formy git reset [<commit>] [paths...], która zresetuje podane ścieżki do ich stanu z podanego commita. Jeśli ścieżki nie są podane, całe drzewo jest resetowane, a jeśli commit nie jest podany, przyjmuje się, że jest HEAD (bieżący commit). Checkout, diff, log, chociaż dokładna semantyka jest różna), więc nie powinno to być zbyt zaskakujące.

Na przykład, git reset other-branch path/to/foo resetuje wszystko w path/to/foo do swojego stanu w other-branch, git reset -- . resetuje bieżący katalog do swojego stanu w HEAD, a Prosty git reset resetuje wszystko do swojego stanu w HEAD.

Główny opcje drzewa roboczego i indeksu

Istnieją cztery główne opcje do kontrolowania tego, co dzieje się z drzewem roboczym i indeksem podczas resetowania.

Pamiętaj, że indeks jest "miejscem postoju" git - to miejsce, gdzie rzeczy idą, kiedy mówisz git add w przygotowaniu do commit.

  • --hard sprawia, że wszystko pasuje do commit, który zresetowałeś. Prawdopodobnie jest to najłatwiejsze do zrozumienia. Wszystkie Twoje lokalne zmiany zostają zablokowane. Jednym z podstawowych zastosowań jest zdmuchnięcie pracy, ale nie przełączanie commity: git reset --hard oznacza git reset --hard HEAD, tzn. nie zmieniaj gałęzi lecz pozbądź się wszystkich lokalnych zmian. Drugi to po prostu przenoszenie gałęzi z jednego miejsca do drugiego i synchronizowanie drzewa indeksów/prac. to jest ten, który naprawdę może sprawić, że stracisz pracę, ponieważ modyfikuje twoje drzewo pracy. bądź bardzo pewien, że chcesz wyrzucić lokalną pracę, zanim uruchomisz jakiekolwiek reset --hard.

  • --mixed jest wartością domyślną, tzn. git reset oznacza git reset --mixed. Resetuje indeks, ale nie drzewo robocze. To oznacza to, że wszystkie Twoje pliki są nienaruszone, ale wszelkie różnice między oryginalnym zatwierdzeniem a tym, do którego zresetowałeś, będą wyświetlane jako lokalne modyfikacje (lub pliki nie śledzone) ze statusem git. Użyj tego, gdy zdasz sobie sprawę, że dokonałeś złych commitów, ale chcesz zachować całą pracę, którą wykonałeś, aby móc ją naprawić i ponownie wprowadzić. Aby zatwierdzić, musisz ponownie dodać pliki do indeksu (git add ...).

  • --soft nie dotyka drzewa roboczego indeksu lub . Wszystkie Twoje pliki są nienaruszone podobnie jak w przypadku --mixed, ale wszystkie zmiany są wyświetlane jako {[33] } ze statusem git (tzn. sprawdzone w przygotowaniu do zatwierdzania). Użyj tego, gdy zdasz sobie sprawę, że dokonałeś złych commitów, ale praca jest dobra - wszystko, co musisz zrobić, to przywrócić ją inaczej. Indeks jest nietknięty, więc możesz natychmiast zatwierdzić zmiany, jeśli chcesz - Wynik zmiany będzie miał taką samą zawartość, jak w miejscu, w którym byłeś przed zresetowaniem.

  • --merge został dodany niedawno i ma na celu pomóc w przerwaniu nieudanego / align = "left" / Jest to konieczne, ponieważ git merge pozwoli na próbę połączenia z drzewem brudnej pracy (z lokalnymi modyfikacjami), o ile te modyfikacje znajdują się w plikach nienaruszonych przez scalenie. git reset --merge resetuje indeks (podobnie jak --mixed - wszystkie zmiany pojawiają się jako modyfikacje lokalne) i resetuje pliki, których dotyczy scalenie, ale pozostawia pozostałe w spokoju. Mam nadzieję, że to przywróci wszystko do tego, jak było przed złym połączeniem. Zazwyczaj używasz go jako git reset --merge (czyli git reset --merge HEAD), ponieważ tylko chcesz zresetować połączenie, a nie przenieść gałąź. (HEAD nie została jeszcze zaktualizowana, ponieważ połączenie nie powiodło się)

    Aby być bardziej konkretnym, Załóżmy, że zmodyfikowałeś pliki A i B i spróbujesz scalić w gałęzi, która zmodyfikowała pliki C i D. połączenie nie powiedzie się z jakiegoś powodu i zdecydujesz się je przerwać. Używasz git reset --merge. Przywraca C i D do tego, jak były w HEAD, ale zostawia Twoje modyfikacje A i B same, ponieważ nie były częścią próby / align = "left" /

Chcesz wiedzieć więcej?

Myślę, że man git reset jest naprawdę dobry do tego - być może potrzebujesz trochę poczucia sposobu, w jaki git działa, aby naprawdę pogrążyć się w tym. W szczególności, jeśli poświęcisz trochę czasu, aby uważnie je przeczytać, te tabele wyszczególniające Stany plików w indeksie i drzewie roboczym dla wszystkich różnych opcji i przypadków są bardzo pomocne. (Ale tak, są bardzo gęste - przekazują strasznie dużo powyższych informacji w bardzo zwięzły forma.)

Dziwny zapis

"dziwna notacja" (HEAD^ i HEAD~1), o których wspomniałeś, jest po prostu skrótem do określania commitów, bez konieczności używania nazwy skrótu, takiej jak 3ebe3f6. Jest to w pełni udokumentowane w " określanie wersji " sekcja strony podręcznika git-rev-parse, z wieloma przykładami i pokrewną składnią. Karetka i tylda oznaczają różne rzeczy :

  • HEAD~ jest skrótem od HEAD~1 i oznacza pierwszy commit rodzic. HEAD~2 oznacza pierwszego rodzica commita. Pomyśl o HEAD~n jako O" n-tym przed głową "lub O"N-tym przodku głowy".
  • HEAD^ (lub HEAD^1) oznacza również pierwszy rodzic commita. HEAD^2 oznacza drugi rodzic commita . Pamiętaj, że normalny commit scalający ma dwóch rodziców - pierwszy rodzic to commit scalony, a drugi rodzic to commit, który został scalony. Ogólnie rzecz biorąc, może mieć w rzeczywistości arbitralnie wielu rodziców (ośmiornica merges).
  • operatory ^ i ~ mogą być połączone razem, jak w HEAD~3^2, drugi rodzic przodka trzeciej generacjiHEAD, HEAD^^2, drugi rodzic pierwszego rodzica HEAD, a nawet HEAD^^^, co jest równoważne HEAD~3.

caret i tilde

 1020
Author: Cascabel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 14:26:55

Pamiętaj, że w git Masz:

  • the HEAD pointer , który informuje, nad jakim commitem pracujesz
  • drzewo robocze , które reprezentuje stan plików w systemie
  • W 2004 roku, po raz pierwszy w historii, w 2006 roku, w Polsce, w 2007 roku, w Polsce, w 2008 roku, w Polsce, w 2009 roku, w Polsce, w 2009 roku, w Polsce, w 2009 roku, w Polsce, w 2009 roku, w Polsce, w 2009 roku, w Polsce, w 2009 roku, w Polsce, w 2009 roku, w Polsce i na świecie.]}

Proszę dołączyć szczegółowe wyjaśnienia dotyczące:

--hard, --soft oraz --merge;

W rosnącej kolejności niebezpieczeństwa:

  • --soft porusza się HEAD, ale nie dotyka miejsca postoju ani drzewa roboczego.
  • --mixed przenosi HEAD i aktualizuje miejsce postoju, ale nie drzewo robocze.
  • --merge przenosi HEAD, resetuje miejsce postoju i próbuje przenieść wszystkie zmiany w roboczym drzewie do nowego drzewa roboczego.
  • --hard ruchy HEAD i dostosowuje obszar postoju i drzewo robocze do nowego HEAD, wyrzucam wszystko.

Konkretne przypadki użycia i przepływy pracy;

  • Użyj --soft, Gdy chcesz przejść do innego commita i łatać rzeczy bez "utraty swojego miejsca". To rzadkość, że tego potrzebujesz.

--

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

--

  • Użyj --mixed (która jest domyślna), gdy chcesz zobaczyć, jak wyglądają zmiany w innym commicie, ale nie chcesz stracić już żadnych zmian mam.

  • Użyj --merge, Gdy chcesz przenieść się do nowego miejsca, ale włącz zmiany, które już masz, do działającego drzewa.

  • Użyj --hard, aby wymazać wszystko i rozpocząć nową listę przy Nowym commicie.

 82
Author: John Feminella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-27 17:08:11

Post Reset Demystified na blogu Pro Git daje bardzo no-brainer Wyjaśnienie na git reset i git checkout.

Po całej pomocnej dyskusji na górze tego postu, autor redukuje Zasady do następujących prostych trzech kroków:

To w zasadzie wszystko. Polecenie reset nadpisuje te trzy drzewa w określonej kolejności, zatrzymując się, gdy je polecisz.
  1. przenieść cokolwiek gałąź HEAD wskazuje na (stop if --soft)
  2. następnie, aby Indeks wyglądał tak (zatrzymaj tutaj, chyba że --hard)
  3. następnie spraw, aby katalog roboczy wyglądał tak

Są też opcje --merge i --keep, ale na razie wolałbym, żeby było prościej - to będzie dla innego artykułu.

 35
Author: Daniel Hershcovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-30 13:25:44

Kiedy zatwierdzasz coś do Gita, musisz najpierw dodać do indeksu swoje zmiany. Oznacza to, że musisz dodać wszystkie pliki, które chcesz umieścić w tym zatwierdzeniu, zanim git uzna je za część zatwierdzania. Najpierw przyjrzyjmy się obrazowi repo Gita: Tutaj wpisz opis obrazka

Teraz to proste. Musimy pracować w working directory, tworząc pliki, katalogi i w ogóle. Zmiany te nie są śledzone. Aby były śledzone, musimy dodać je do indeksu git za pomocą git add polecenie. Po dodaniu ich do indeksu git. Możemy teraz zatwierdzić te zmiany, jeśli chcemy je przenieść do repozytorium git.

Ale nagle dowiedzieliśmy się, że mamy jeden dodatkowy plik, który dodaliśmy do indeksu, nie jest wymagany do wciśnięcia w repozytorium git. To znaczy, że nie chcemy tego pliku w indeksie. Teraz pytanie brzmi, jak usunąć ten plik z indeksu git, ponieważ użyliśmy git add aby umieścić go w indeksie, logicznym byłoby użycie git rm? Źle! git RM po prostu usunie plik i doda go do indeksu. Więc co teraz zrobić:

Użycie: -

Git reset

Czyści Twój indeks, pozostawia Twój katalog roboczy nietknięty. (po prostu odinstaluj wszystko).

Może być używany z wieloma opcjami. Istnieją trzy główne opcje do użycia z git reset: --hard, -- soft I --mixed . Wpływają one na to, co get jest reset oprócz wskaźnika głowy, gdy reset.

Po pierwsze, --hard resetuje wszystko. Twój bieżący katalog byłby dokładnie taki, jak gdybyś cały czas śledził tę gałąź. Katalog roboczy i indeks są zmieniane na ten commit. Jest to wersja, której używam najczęściej. git reset --hard jest czymś w rodzaju svn revert .

Następnie, całkowite przeciwieństwo, - soft , nie resetuje drzewa roboczego ani indeksu. Przesuwa tylko wskaźnik głowy. To pozostawia Twój prąd wprowadź zmiany inne niż zmiany, które zmieniasz na miejsce w katalogu i "zainscenizuj" do zatwierdzenia. Jeśli tworzysz commit lokalnie, ale nie wypchnąłeś go na serwer git, możesz zresetować poprzedni commit i ponownie go zatwierdzić.

Wreszcie, --mixed resetuje indeks, ale nie drzewo robocze. Tak więc wszystkie zmiany nadal tam są, ale są "unstaged" i musiałyby być git add lub git commit-a . używamy tego czasami, jeśli popełniliśmy więcej niż zamierzaliśmy za pomocą git commit-a, możemy wycofać commit za pomocą git reset --mixed, dodać rzeczy, które chcemy zatwierdzić i po prostu je zatwierdzić.

różnica między git revert i GIT reset :-


W prostych słowach, git reset jest poleceniem "fix-commited mistakes" i git revert jest poleceniem "fix-commited mistakes".

Oznacza to, że jeśli popełniliśmy jakiś błąd w jakimś change and commited and pushed the same to git repo, then git revert jest rozwiązaniem. A jeśli w przypadku, gdy zidentyfikowaliśmy ten sam błąd przed naciśnięciem / zatwierdzeniem, możemy użyć git reset, aby rozwiązać problem.

Mam nadzieję, że pomoże Ci pozbyć się zamieszania.

 25
Author: love,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-07 17:15:15

TL;DR

git reset resetuje inscenizację do ostatniego zatwierdzenia. Użyj --hard, aby zresetować pliki w katalogu roboczym do ostatniego zatwierdzenia.

DŁUŻSZA WERSJA

Ale to jest oczywiście uproszczone, stąd wiele dość gadatliwych odpowiedzi. Bardziej sensowne było dla mnie przeczytanie git reset w kontekście cofania zmian. Np. ZOBACZ TO:

Jeśli git revert jest "bezpiecznym" sposobem cofania zmian, możesz myśleć o git reset jako niebezpieczna metoda. Gdy cofasz z Git reset (i commity nie są już referowane przez żadne ref lub reflog), jest nie ma możliwości odzyskania oryginalnej kopii-jest to trwałe cofnięcie. Care must być brane podczas korzystania z tego narzędzia, ponieważ jest to jedna z niewielu komend Git, która może stracić pracę.

Z https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

I to

Na poziomie commit, resetowanie jest sposobem na przeniesienie wierzchołka gałęzi do innego / align = "left" / Można to wykorzystać do usunięcia commitów z bieżącej gałęzi.

Od https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations{[19]

 6
Author: Snowcrash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-13 18:06:53

należy pamiętać, że jest to uproszczone wyjaśnienie przeznaczone jako pierwszy krok w poszukiwaniu zrozumienia tej złożonej funkcjonalności.

Może być pomocny dla wizualnych uczniów, którzy chcą wizualizować jak wygląda ich stan projektu po każdym z tych poleceń:


Dla tych, którzy używają terminala z włączonym kolorem (Git config --global color.UI auto):

git reset --soft A i zobaczysz rzeczy B I C na Zielono (zainscenizowane i gotowe do popełnienia)

git reset --mixed A (lub git reset A) i zobaczysz rzeczy B I C w kolorze czerwonym (unstaged i gotowe do inscenizacji (zielony), a następnie popełnione)

git reset --hard A i nie będziesz już widział zmian B I C gdziekolwiek (będzie tak, jakby nigdy nie istniały)


W 2007 roku firma została założona przez firmę SourceTree.]}

git reset --soft A i zobaczysz rzeczy B I C w obszarze' zainscenizowane pliki ' gotowe do zatwierdzenia

git reset --mixed A (lub git reset A) i zobaczysz rzeczy B I C w obszarze' unstaged files ' gotowe do być przeniesione do inscenizacji, a następnie popełnione

git reset --hard A i nie będziesz już widział zmian B I C gdziekolwiek (będzie tak, jakby nigdy nie istniały)

 2
Author: timhc22,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-03 11:10:26

Checkout wskazuje głowę na konkretny commit.

Reset wskazuje gałąź na określony commit. (Gałąź jest wskaźnikiem do commita.)

nawiasem mówiąc, jeśli Twoja głowa nie wskazuje na commit, który jest również wskazywany przez gałąź, to masz odłączoną głowę. (okazało się, że się myli. Zobacz komentarze...)

 1
Author: Ian Warburton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-16 15:31:15