Sprawdzasz stary commit i utrzymujesz head w gałęzi master?

85

Obecnie w celu przełączenia się na inne zatwierdzenie git (na tej samej gałęzi ... właściwie na gałęzi master!), Wykonuję polecenie

git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

Teraz za każdym razem, gdy to robię, dupek mówi mi, że mam teraz odłączoną głowę. Jak przejść do starszego zatwierdzenia i nadal utrzymywać głowę w tej samej gałęzi?

pożarł elizjum
źródło
1
Po wykonaniu tego polecenia, ref HEAD zmienia się na to zatwierdzenie. Nie ma sensu chcieć, aby GŁOWA wskazywała również gdzie indziej.
Greg Hewgill,
Z tego, co rozumiem z przesłania gita, nie wskazuje on nigdzie , co jest niepożądane.
pożarł elizjum
1
Na wiadomość Git pokazy podczas wymeldowania specyficzny popełnić tak mówi „głowa jest teraz w ea3d5ed ...”, który mówi, że głowa jest wskazując gdzieś. Po prostu wskazuje miejsce, które nie ma innej nazwy poza HEAD (w tej chwili, ponieważ a git checkoutdo innego zatwierdzenia lub nazwy gałęzi przeniesie HEAD do tego nowego miejsca).
Greg Hewgill,
Czy udzielone odpowiedzi odpowiednio to wyjaśniają, czy może jest coś, co moglibyśmy wyjaśnić bardziej jasno? Z przyjemnością wyjaśnię ci moją odpowiedź, jeśli nie odpowie na twoje pytanie.
Brian Campbell
Jeśli przyszedłeś tutaj, szukając sposobu na sprawdzenie innego zatwierdzenia, zachowując HEAD całkowicie niezmieniony (na przykład w celu powrotu do starszego zatwierdzenia): git revert --no-commit 0766c053..HEADzrobi to, gdzie 0766c053jest zatwierdzenie, które chcesz sprawdzić. To pochodzi ze strony stackoverflow.com/a/21718540/525872 .
Jo Liss

Odpowiedzi:

193

Przez większość czasu, kiedy to robię, płacę do oddziału tymczasowego:

git checkout -b temp-branch-name ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a

Następnie, gdy skończę, po prostu usuwam gałąź

Nick Canzoneri
źródło
80

To zależy od tego, co chcesz zrobić, kiedy sprawdzasz to zatwierdzenie. Jeśli wszystko, co robisz, to sprawdzanie go, aby móc zbudować lub przetestować tę wersję, to nie ma nic złego w pracy z odłączoną głową. Pamiętaj tylko, aby sprawdzić aktualną gałąź przed wykonaniem jakichkolwiek zatwierdzeń ( git checkout masterna przykład), aby nie tworzyć zatwierdzeń, które nie są zawarte w żadnej gałęzi.

Jeśli jednak chcesz zrobić więcej zatwierdzeń od tego momentu, powinieneś utworzyć gałąź. Jeśli zrobisz zatwierdzenia, do których gałąź nie odwołuje się, mogą łatwo się zgubić i ostatecznie zostaną wyczyszczone przez garbage collector git, ponieważ nic się do nich nie odnosi. Możesz utworzyć nową gałąź, uruchamiając:

git checkout -b newbranch ea3d5ed

Aby pomóc w wizualizacji, oto kilka diagramów pokazujących, jak praca z odłączoną głową różni się od pracy na gałęzi.

Zacznijmy od 3 zatwierdzeń master, A, B i C. masterto bieżąca gałąź, więc HEADwskazuje master, która wskazuje na zatwierdzenie C.

ABC
* - * - * <- master <- HEAD

Teraz, jeśli zatwierdzimy, git utworzy zatwierdzenie, które ma C jako rodzica (ponieważ jest to bieżące zatwierdzenie, wskazywane przez HEADvia master) i zaktualizuje się, masteraby wskazywało na to nowe zatwierdzenie. Wszystkie nasze zatwierdzenia są teraz dostępne masteri HEADwskazują na nowe zatwierdzenie master.

ABCD
* - * - * - * <- master <- HEAD

Teraz sprawdźmy B, dając nam oderwany HEAD.

ABCD
* - * - * - * <- master
   ^
    \-- GŁOWA

Tutaj wszystko działa dobrze; możemy przeglądać wszystkie pliki, budować nasz program, testować go, itp. Możemy nawet tworzyć nowe zatwierdzenia; ale jeśli to zrobimy, nie ma gałęzi, na której jesteśmy, więc nie możemy wskazać żadnej gałęzi na to nowe zatwierdzenie. Jedyne, co na to wskazuje, to HEAD:

ABCD
* - * - * - * <- master
    \
     * <- HEAD
     mi

Jeśli później zdecydujemy się sprawdzić masterponownie, nie będzie nic odnoszącego się do E.

ABCD
* - * - * - * <- master <- HEAD
    \
     *
     mi

Ponieważ nic do tego nie odnosi się, może to być trudne do znalezienia, a git rozważa zmiany bez odniesień do porzucenia (zdarzają się one dość często, jeśli dokonujesz rebase'u, wprowadzasz łatki do squasha lub wykonujesz inne zabawne manipulacje historią; zwykle reprezentują one na którym już Ci nie zależy). Po pewnym czasie git uzna to za śmieci do odrzucenia przy następnym uruchomieniu czyszczenia pamięci.

Tak więc, zamiast sprawdzać gołą wersję i uzyskiwać odłączoną głowę, jeśli czujesz, że zamierzasz wykonać więcej zatwierdzeń, powinieneś użyć git checkout -b branch Bdo stworzenia gałęzi i sprawdzenia. Teraz twoje zatwierdzenia nie zostaną utracone, ponieważ zostaną uwzględnione w gałęzi, do której możesz łatwo się odwołać i połączyć później.

ABCD
* - * - * - * <- master
   ^
    \ - gałąź <- HEAD

Jeśli zapomnisz o tym zrobić i utworzysz zatwierdzenia z gałęzi, nie musisz się martwić. Możesz utworzyć gałąź odwołującą się do wersji głowy za pomocą git checkout -b branch. Jeśli już przełączyłeś się z powrotem do mastergałęzi i zdałeś sobie sprawę, że zapomniałeś zbłąkanego zatwierdzenia, możesz go znaleźć, używając git reflog, które pokaże historię tego, na HEADco wskazywały zmiany w ciągu ostatnich kilku dni. Wszystko, co nadal znajduje się w reflogu, nie będzie zbierane jako śmieci i generalnie odwołania są przechowywane w reflogu przez co najmniej 30 dni.

Brian Campbell
źródło
Nie jest dla mnie do końca jasne, dlaczego przy kasie starego zobowiązania głowa się odrywa . Może problem polega na tym, co oznacza odłączona głowa? Z drugiej strony, jeśli sprawdzenie starego commit z odłączoną głową tylko go zgubi, dlaczego ktokolwiek miałby to robić? Tylko po to, żeby się bawić i próbować? Dlaczego git na to pozwala?
pożarł elizjum
5
@devoured elysium "odłączona głowa" oznacza, że ​​masz odniesienie, HEADktóre wskazuje bezpośrednio na SHA-1 zatwierdzenia, zamiast wskazywać na gałąź, która z kolei wskazuje na zatwierdzenie. Ponieważ twoja głowa nie odwołuje się do gałęzi, Git nie wie, którą gałąź zaktualizować po dodaniu nowych zatwierdzeń. Jak wyjaśniłem na początku mojej odpowiedzi, dobrze jest mieć odłączoną głowę, jeśli wracasz do starej wersji tylko po to, aby zbudować lub przetestować kod; zawsze możesz wrócić do oddziału za pomocą git checkout masterlub w podobny sposób. To tylko problem, jeśli popełnisz błąd, mając oderwaną głowę.
Brian Campbell,
@BrianCampbell - Po dokonaniu zatwierdzeń na gałęzi (w której aktualnie znajduje się twoja głowa), czy następnie łączysz gałąź w B i łączysz B w master. Co powinieneś teraz zrobić?
amey1908
Twoje wyjaśnienie sprawiło, że kilka innych rzeczy „zaskoczyło”. Dziękuję Ci. Mogłem w końcu zrozumieć git ...
Joe
8

Jeśli chcesz po prostu wrócić do wcześniejszego zatwierdzenia, aby grać z nim bez dokonywania jakichkolwiek zmian, możesz to zrobić

git co <previous-commit-id>

po tym poleceniu będziesz na gałęzi o nazwie „(brak gałęzi)”.

Potwierdź to do

git br

Po zagraniu tym wcześniej zatwierdzonym kodem możesz przełączyć się na gałąź, w której byłeś

git co <the-branch-you-were-on>

„(Brak gałęzi)” zostanie automatycznie usunięty. W ten sposób nie musisz tworzyć tymczasowej gałęzi.

Zack Xu
źródło
5

HEAD Gita to po prostu wskaźnik, który mówi, co znajduje się w katalogu roboczym. Jeśli chcesz sprawdzić zatwierdzenie, które nie jest nagłówkiem gałęzi, po prostu musisz przekierować HEAD tak, aby wskazywał na ten commit. Nie da się tego obejść. Możesz utworzyć tymczasową gałąź w tym zatwierdzeniu, ale mimo to HEAD zostanie odesłany od mastera.

To krótkie wyjaśnienie. Mamy nadzieję, że poniższa szczegółowość pomoże zrozumieć, czym różnią się HEAD i mistrz:

Zwykle wygląda to tak:

C ← refs/heads/master ← HEAD 
↓
B
↓
A

To znaczy: „Rodzicem C jest B, a rodzicem B jest A. Wzorzec gałęzi wskazuje na C, a ja aktualnie sprawdziłem zawartość wzorca. Ponadto, kiedy zatwierdzę, master zostanie zaktualizowany. ”

Są w tym domniemane pewne założenia, które są niezbędne do dokładnego zrozumienia wykresu zatwierdzenia. Mianowicie, zatwierdzenia odnoszą się tylko do ich rodziców, a zawartość brancha to te commity (i tylko te zatwierdzenia), do których można dotrzeć, podążając za linkami nadrzędnymi. (Niezmodyfikowana) zawartość drzewa roboczego i indeks muszą odpowiadać zatwierdzeniu nazwanemu przez HEAD, pośrednio („symboliczne”) lub bezpośrednio („odłączone”).

Tak więc, jeśli chcesz sprawdzić stare zatwierdzenie, HEAD musi zostać zaktualizowany, aby wskazywał na pożądane zatwierdzenie. git-checkoutrobi właśnie to:

C ← refs/heads/master 
↓
B ← HEAD
↓
A

Teraz zostawiłeś swoją gałąź za sobą, ponieważ patrzysz na coś starego. To zupełnie OK, jak spokojnie podpowiada ci rada „oderwanej głowy” (moje podkreślenie):

Możesz się rozglądać, wprowadzać eksperymentalne zmiany i zatwierdzać je, a także odrzucać wszelkie zmiany wprowadzone w tym stanie bez wpływu na gałęzie , wykonując kolejne pobranie.

Z drugiej strony, resetując gałąź, otrzymujesz również HEAD tam, gdzie to konieczne, miałoby to zupełnie inny efekt!

C
↓
B ← refs/heads/master ← HEAD
↓
A

Commit C stanie się śmieciem, ponieważ zadeklarowałeś, że nie chcesz, aby był już częścią gałęzi master.

Krótko mówiąc, wszystko, co musisz zrobić, to zrozumieć, co oznacza git przez „HEAD” - tam, gdzie jesteś , a nie tam, gdzie jest jakaś gałąź. A jeśli to, gdzie jesteś, różni się od miejsca, w którym znajduje się gałąź, nie ma innego wyjścia, jak tylko użyć odłączonej HEAD.

(Być może zajrzyj również do GitHub, gitk lub gitweb, aby przejrzeć historię zmian, jeśli wykolejenie HEAD nadal cię irytuje.)

Josh Lee
źródło
1

Pytanie jest trochę niejasne, ale jeśli chcesz po prostu zmienić pliki w swoim drzewie roboczym, możesz po prostu zrobić to:

git checkout [commit|branch] -- .

Możesz wtedy wprowadzić zmiany i utworzyć nowe zatwierdzenie, jeśli chcesz. Jest to czasami przydatne.

Lari Hotari
źródło
0

Myślę, że rozumiem twoje pytania. Oto, co znalazłem, aby go rozwiązać. i nie ma rozwiązania GUI tego rozwiązania, możesz użyć tylko polecenia, aby go rozwiązać, i jest to naprawdę proste.

krok 1: stwórz tag starego zatwierdzenia, do którego chcesz wrócić.

jak tag v2.0

Krok 2: Git Checkout v2.0

oto jest, teraz twój HEAD wskazuje na zatwierdzenie 'v2.0', ale master wciąż wskazuje na ostatnie zatwierdzenie.

C:\Program Files\Git\doc\git\html\git-checkout.html ten dokument może ci pomóc

lub wpisz git help <checkout>

Lion Lai
źródło