Naprawić odłączoną głowę Git?

1453

Pracowałem trochę w moim repozytorium i zauważyłem, że plik zawiera zmiany lokalne. Nie chciałem ich już, więc usunąłem plik, myśląc, że mogę po prostu pobrać świeżą kopię. Chciałem zrobić odpowiednik Git

svn up .

Korzystanie git pullnie wydawało się działać. Niektóre losowe wyszukiwanie doprowadziło mnie do strony, na której ktoś polecił zrobić

git checkout HEAD^ src/

( srcto katalog zawierający usunięty plik).

Teraz dowiaduję się, że mam odłączoną głowę. Nie mam pojęcia co to jest. Jak mogę cofnąć?

Daniel
źródło
69
git checkout masterodeśle cię z powrotem do głównej gałęzi. Jeśli chcesz usunąć wszelkie zmiany kopii roboczej, prawdopodobnie chciałeś to zrobić git reset --hard.
Abe Voelker,
jeśli nie zobowiązałeś się, mógłbyś to zrobićgit checkout -- src/
thesummersign
Spróbuj tego: link . W skróciecreate temp branch - checkout temp branch - checkout master - delete temp branch
fidev
@AbeVoelker Co miałeś na myśli przez komentarze working copy changes? Czy masz na myśli zmiany, które wprowadziłeś do plików po sprawdzeniu innego zatwierdzenia (tj. Zmiany, które wprowadziłeś, gdy byłeś w stanie odłączonym)?
Minh Tran,

Odpowiedzi:

2147

Odłączona głowa oznacza, że ​​nie jesteś już w gałęzi, sprawdziłeś pojedyncze zatwierdzenie w historii (w tym przypadku zatwierdzenie poprzedzające HEAD, tj. HEAD ^).

Jeśli chcesz usunąć zmiany związane z odłączonym HEAD

Musisz tylko sprawdzić kasę, w której byłeś, np

git checkout master

Następnym razem, gdy zmienisz plik i chcesz przywrócić go do stanu z indeksu, nie usuwaj go najpierw, po prostu zrób

git checkout -- path/to/foo

Spowoduje to przywrócenie pliku foo do stanu, w którym znajduje się w indeksie.

Jeśli chcesz zachować zmiany związane z odłączonym HEAD

  1. Uruchom git branch tmp- spowoduje to zapisanie zmian w nowej gałęzi o nazwie tmp.
  2. Biegać git checkout master
  3. Jeśli chcesz uwzględnić zmiany, które wprowadziłeś master, uruchom git merge tmpz masteroddziału. masterPo uruchomieniu powinieneś być na gałęzi git checkout master.
ralphtheninja
źródło
6
„Spowoduje to przywrócenie pliku foo do stanu, w jakim był przed wprowadzeniem jakichkolwiek zmian.” -> przywróci go do stanu, w którym znajduje się w indeksie - edytuj
Mr_and_Mrs_D
87
Dlaczego ten błąd występuje przede wszystkim? Jest to jedna z rzeczy, za którą nienawidzę git - czasami całkowicie losowe zachowanie. Nigdy nie miałem takich problemów z Mercurialem.
Violet Giraffe
97
@VioletGiraffe Nie jest to ani błąd, ani coś losowego - jest to po prostu stan, w którym znajduje się twoje repozytorium, kiedy kasujesz poprzednie zatwierdzenie. „Odłączona głowa” służy jako ostrzeżenie, które możesz chcieć utworzyć lub wskazać gałąź, jeśli zamierzasz wykonywać jakąkolwiek pracę od tego miejsca. Ale jeśli chcesz po prostu wyświetlić ten tag lub zatwierdzić, nie ma nic złego w byciu w stanie odłączonej głowy.
Neil Neyman
22
Nie rób tego, jeśli zobowiązałeś się do odłączonej głowy, zobacz inne odpowiedzi. Jeśli tak, możesz sprawdzić poprzednie wzmianki wPrevious HEAD position was 7426948...
KCD
9
@VioletGiraffe: masz model mentalny tego, co się dzieje w oparciu o Mercurial, ale używasz Git. Jeśli nie chcesz dopasowywać swojego modelu mentalnego do modelu Gita, rzeczy będą wyglądać losowo. To tak, jakbyś chodził na zewnątrz z założonymi goglami VR i myślisz, że lecisz samolotem, ale naprawdę przecinasz ulicę. Zostaniesz potrącony przez samochody.
iconoclast
477

Jeśli zmieniłeś pliki, których nie chcesz utracić, możesz je przesłać. Zatwierdziłem je w trybie odłączonym, a następnie możesz przejść do gałęzi tymczasowej, aby później zintegrować się z modułem głównym.

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

Wypakowany z:

Co zrobić z zatwierdzeniem dokonanym w odłączonej głowie

Toni Gamez
źródło
27
Uważam to za preferowane rozwiązanie - szczególnie jeśli chcesz zachować zmiany, które wprowadziłeś podczas sprawdzania poszczególnych wersji.
adswebwork
10
@adswebwork: Zgadzam się. Wszystkie pozostałe odpowiedzi sugerują powrót do poprzedniego stanu i utratę zmian dokonanych lokalnie w stanie odłączonej głowy.
Sk8erPeter
6
dlaczego nie git stash? Ponieważ to pierwsza rzecz, jaka przychodzi mi do głowy. utworzenie nowego oddziału będzie przesadą.
thesummersign
2
możesz także, git rebase my-temporary-worka następnie usunąć gałąź, git branch -d my-temporary-workaby wyglądało to tak, jakbyś zobowiązał się do właściwej gałęzi.
Zoltán
@geekay git stashwydaje się być idealnym narzędziem do tego przypadku. Czy możesz napisać odpowiedź z sugerowanymi krokami, aby to osiągnąć?
Zoltán
156

Rozwiązanie bez tworzenia gałęzi tymczasowej.

Jak wyjść („naprawić”) odłączony stan HEAD, gdy już coś zmieniłeś w tym trybie i, opcjonalnie, chcesz zapisać zmiany:

  1. Zatwierdź zmiany, które chcesz zachować. Jeśli chcesz przejąć którąkolwiek ze zmian wprowadzonych w odłączonym stanie HEAD, zatwierdź ją. Lubić:

    git commit -a -m "your commit message"
    
  2. Odrzuć zmiany, których nie chcesz zachować. Twardy reset spowoduje odrzucenie wszelkich niezatwierdzonych zmian dokonanych w stanie odłączonego HEAD:

    git reset --hard
    

    (Bez tego krok 3 nie powiódłby się, narzekając na zmodyfikowane nieprzypisane pliki w odłączonym HEAD.)

  3. Sprawdź swój oddział. Wyjdź z odłączonego stanu HEAD, sprawdzając gałąź, nad którą pracowałeś wcześniej, na przykład:

    git checkout master
    
  4. Przejmij swoje zobowiązania. Możesz teraz przejąć zatwierdzenia dokonane w stanie odłączonym HEAD przez wybieranie, jak pokazano w mojej odpowiedzi na inne pytanie .

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    
Tanius
źródło
git reset --hardZostał dokładnie miałem potrzeby, bo chcę upstream być źródłem i lokalne zmiany powinny zostać usunięte.
Markus Zeller,
Świetna odpowiedź, to zadziałało dla mnie
MGLondon
130

Odłączona głowa oznacza:

  1. Nie jesteś już w oddziale,
  2. Sprawdziłeś jedno zatwierdzenie w historii

Jeśli nie masz żadnych zmian: możesz przełączyć na master, stosując następującą komendę

  git checkout master

Jeśli masz zmiany, które chcesz zachować:

W przypadku odłączonego HEAD, zatwierdzenia działają normalnie, tyle że żadna nazwana gałąź nie jest aktualizowana. Aby zaktualizować gałąź główną z zatwierdzonymi zmianami, utwórz gałąź tymczasową tam, gdzie jesteś (w ten sposób gałąź tymczasowa będzie miała wszystkie zatwierdzone zmiany, które wprowadziłeś w odłączonym HEAD), a następnie przełącz się na gałąź główną i połącz gałąź tymczasową z mistrz.

git branch  temp
git checkout master
git merge temp
Razan Paul
źródło
2
idealne, a następnie po usunięciu temp gałęzi
Davi Menezes
64

Oto, co właśnie zrobiłem po tym, jak zdałem sobie sprawę, że jestem zdystansowany i już dokonałem pewnych zmian.

Popełniłem zmiany.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

Pamiętałem skrót (1fe56ad) zatwierdzenia. Potem sprawdziłem gałąź, w której powinienem być.

$ git checkout master
Switched to branch 'master'

W końcu zastosowałem zmiany zatwierdzenia do oddziału.

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

Myślę, że jest to trochę łatwiejsze niż utworzenie tymczasowej gałęzi.

Philippe Gerber
źródło
2
To powinna być odpowiedź. Odzyskuje twoje nukowane pliki.
BlindWanderer
2
Tak, to naprawdę najprostsza rzecz do zrobienia - wystarczająco prosta do zapamiętania bez przeszukiwania sieci następnym razem. Zatwierdź, zanotuj skrót, wróć do oddziału, do którego miałeś się zobowiązać, i git cherry-pick <hash>.
Mason,
Dzięki za rozwiązanie. To pomogło. Dodam też, że musiałem zrobić „master git push origin”, aby mój master i origin / master wskazywali na to samo zatwierdzenie.
turnip424
1
Jest to zasadniczo odpowiedź Taniusa (opublikowana ponad rok wcześniej).
Peter Mortensen,
Dzięki temu wesołemu kilofowi cofnij ostatnie zmiany odczepiania głowy
Omega Cube
54

Jeśli wprowadziłeś jakieś zmiany, a następnie zdałeś sobie sprawę, że jesteś na odłączonej głowie, istnieje proste rozwiązanie tego problemu: skrytka -> kasa główna -> skrytka pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

Będziesz miał swoje niezaangażowane zmiany i normalną „dołączoną” głowicę, jakby nic się nie wydarzyło.

mojuba
źródło
2
Dodałem do zakładek tego złego chłopca - ratuje tworzenie oddziału tymczasowego. Pracowałem przysmak.
Tim Tyler,
1
Często po przejściu do podmoduła git i wprowadzeniu do niego zmian często znajduję się w stanie odłączonym HEAD. Uważam, że jest to najlepsze i najłatwiejsze rozwiązanie problemu, dzięki któremu mogę zachować moje zmiany.
user5359531,
1
To nie działa, jeśli już zatwierdziłeś zmiany w stanie odłączonym?
Danijel
40

Kiedy wypisujesz konkretne zatwierdzenie git, kończysz w stanie odłączonej głowy ... to znaczy, twoja kopia robocza nie odzwierciedla już stanu nazwanego odwołania (np. „Master”). Jest to przydatne do badania przeszłego stanu repozytorium, ale nie tego, czego chcesz, jeśli faktycznie próbujesz przywrócić zmiany.

Jeśli dokonałeś zmian w określonym pliku i po prostu chcesz je odrzucić, możesz użyć następującego checkoutpolecenia:

git checkout myfile

Spowoduje to odrzucenie wszelkich niezatwierdzonych zmian i przywrócenie pliku do dowolnego stanu, jaki ma w głowie bieżącego oddziału. Jeśli chcesz odrzucić zmiany, które już zatwierdziłeś, możesz użyć resetpolecenia. Na przykład spowoduje to zresetowanie repozytorium do stanu poprzedniego zatwierdzenia, odrzucając wszelkie późniejsze zmiany:

git reset --hard HEAD^

Jeśli jednak udostępniasz repozytorium innym osobom, a git resetmoże być zakłócające (ponieważ usuwa część historii repozytorium). Jeśli już podzieliłeś się zmianami z innymi ludźmi, zwykle chcesz git revertzamiast tego spojrzeć na to , co generuje „anticommit” - to znaczy, tworzy nowe zatwierdzenie, które „cofa” dane zmiany.

Księga Git ma więcej szczegółów.

Larsks
źródło
1
Jak powiedziałem w odpowiedzi @ ralphtheninja, git checkout path/to/foomoże być w konflikcie git checkout some-branch, więc lepiej byłoby użyć git checkout -- path/to/foodo uniknięcia tych konfliktów.
Diego Lago,
30

HEAD jest wskaźnikiem, w wyniku czego wskazuje - bezpośrednio lub pośrednio - na konkretne zatwierdzenie:

Dołączona   GŁOWA oznacza, że ​​jest dołączona do jakiejś gałęzi (tzn. Wskazuje na gałąź).
Indywidualny środek głowy, że to jest nie związane z dowolnym oddziale, czyli zwraca się bezpośrednio do niektórych popełnić.

wprowadź opis zdjęcia tutaj

Innymi słowy:

  • Jeśli wskazuje bezpośrednio na zatwierdzenie , HEAD jest odłączany .
  • Jeśli wskazuje na zatwierdzenie pośrednio (tj. Wskazuje gałąź, która z kolei wskazuje na zatwierdzenie), HEAD jest dołączony .

Aby lepiej zrozumieć sytuacje z podłączoną / odłączoną GŁOWĄ, pokażmy kroki prowadzące do kwadrupletu zdjęć powyżej.

Zaczynamy od tego samego stanu repozytorium (zdjęcia we wszystkich kwadrantach są takie same):

wprowadź opis zdjęcia tutaj


Teraz chcemy wykonać git checkout- z różnych celów w poszczególnych zdjęć (polecenia na nich są przyciemnione, aby podkreślić, że jesteśmy tylko zamiar zastosować te polecenia):

wprowadź opis zdjęcia tutaj


Taka sytuacja występuje po wykonaniu następujących poleceń:

wprowadź opis zdjęcia tutaj

Jak widać, punkty głowa do celu z git checkoutpolecenia - do gałęzi (3 pierwsze wizerunki quadruplet) lub (bezpośrednio) do popełnienia (ostatni obraz quadruplet).

Zmienia się także zawartość katalogu roboczego, aby była zgodna z odpowiednim zatwierdzeniem (migawką), tj. Z zatwierdzeniem wskazanym (bezpośrednio lub pośrednio) przez HEAD.


Jesteśmy teraz w takiej samej sytuacji jak na początku tej odpowiedzi:

wprowadź opis zdjęcia tutaj

MarianD
źródło
6
Nie przeczytałem go, ale głosowałem za ładnymi zdjęciami, które zrobiłeś;).
Carlo Wood,
@Carlo, dzięki!
MarianD
22

Ponieważ „odłączony stan głowy” ma cię w gałęzi tymczasowej, po prostu użyj tego, git checkout -co spowoduje przejście do ostatniej gałęzi, w której byłeś.

Mikrofon
źródło
1
uważaj, stracisz wszelkie zobowiązania popełnione, gdy byłeś w stanie odłączonej głowy.
Ajak6,
@ Ajak6 Naprawdę nie tracisz tych zobowiązań. Są one nadal dostępne za pośrednictwem git reflogi mogą zostać przejęte do nowego oddziału lub git cherry-pickdo istniejącego oddziału. Zobacz to pytanie .
tanius
7

Aby wyjaśnić odpowiedź @Filippe Gerber, oto ona:

chrzanić

Przed cherry-pick, A git checkout masterjest w tym przypadku konieczne. Co więcej, jest ona potrzebna tylko przy commitin detached head.

Timo
źródło
6

Uzupełnienie

Jeśli gałąź, do której chcesz wrócić, była ostatnią dokonaną przez ciebie kasą, możesz po prostu użyć checkout @{-1}. Spowoduje to powrót do poprzedniej kasy.

Ponadto możesz aliasować to polecenie, na przykład, git global --config alias.prevaby wystarczyło wpisać, git prevaby przełączyć się z powrotem do poprzedniej kasy.

David Brower
źródło
4

Bycie w „odłączonej głowie” oznacza, że ​​HEAD odnosi się do konkretnego nienazwanego zatwierdzenia (w przeciwieństwie do nazwanego oddziału) (por. Https://git-scm.com/docs/git-checkout sekcja Odłączona głowa )

Aby rozwiązać problem, wystarczy wybrać gałąź wybraną wcześniej przez

git checkout @{-1}

Poklepać. ANDRIA
źródło
2

Gdy jesteś w sytuacji odłączonej głowy i utworzyłeś nowe pliki, najpierw upewnij się, że te nowe pliki zostały dodane do indeksu, na przykład:

git add .

Ale jeśli zmieniłeś lub usunąłeś tylko istniejące pliki, możesz dodać (-a) i zatwierdzić wiadomość (-m) w tym samym czasie poprzez:

git commit -a -m "my adjustment message"

Następnie możesz po prostu utworzyć nowy oddział z bieżącym stanem za pomocą:

git checkout -b new_branch_name

Będziesz miał nowy oddział, a wszystkie dostosowania będą tam w tym nowym oddziale. Następnie możesz dalej naciskać na zdalne sterowanie i / lub kasować / wyciągać / scalać, jak chcesz.

DZet
źródło
1

Git powiedział mi, jak to zrobić.

jeśli wpiszesz:

git checkout <some-commit_number>

Zapisz status

git add .
git commit -m "some message"

Następnie:

 git push origin HEAD:<name-of-remote-branch>
Sterling Diaz
źródło
1

Chciałem zachować moje zmiany, więc naprawiam to ...

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

to działa dla mnie

CRLZXO
źródło
1

Zwykle HEADwskazuje na gałąź. Gdy nie wskazuje gałęzi, a zamiast tego wskazuje na skrót zatwierdzenia 69e51, oznacza to, że masz odłączony HEAD. Musisz wskazać dwa oddział, aby rozwiązać problem. Możesz zrobić dwie rzeczy, aby to naprawić.

  1. git checkout other_branch // Niemożliwe, gdy potrzebujesz kodu w tym zatwierdzeniu hash
  2. utwórz nowy oddział i wskaż skrót mieszania na nowo utworzony oddział.

HEAD musi wskazywać na gałąź, a hash zatwierdzania nie jest złotą regułą.

Krishnadas PC
źródło
dlatego właśnie miałem ten błąd. Sprawdziłem wersję, a następnie wróciłem do bieżącej / najnowszej wersji zamiast do oddziału, który prawidłowo przymocowałby głowę. Dzięki za pomoc.
Rahul Thakur
1

Odłączona głowa oznacza, że ​​nie sprawdziłeś poprawnie swojego oddziału lub właśnie sprawdziłeś pojedynczy zatwierdzenie.

Jeśli napotkasz taki problem, najpierw ukryj zmiany lokalne, aby ich nie utracić.

Następnie ... sprawdź żądany oddział za pomocą polecenia:

Powiedzmy, że chcesz mieć oddział MyOriginalBranch:

git checkout -b someName origin / MyOriginalBranch

Dhirendra Gautam
źródło
1

prawdopodobnie zrobiłeś git reset --hard origin/your-branch.

Spróbuj po prostu git checkout your-branch

Johnny Cage
źródło
0
git pull origin master

pracował dla mnie. Chodziło tylko o jawne podanie nazwy zdalnego i oddziału.

Amjedonline
źródło
0

W moim przypadku uruchamiam git statusi zobaczyłem, że mam kilka nieśledzonych plików w moim katalogu roboczym.

Po prostu musiałem je wyczyścić (ponieważ ich nie potrzebowałem), aby uruchomić bazę, którą chciałem wykonać.

falsarella
źródło
0

To działa dla mnie, przypisuje nową gałąź dla odłączonej głowy:

git kasa nowa_nazwa_gałęzi_nazwa_nazwy_grupy

Alok Gupta
źródło
0

Odłączony HEAD oznacza, że ​​obecnie nie jesteś w żadnej gałęzi. Jeśli chcesz ZACHOWAĆ bieżące zmiany i po prostu utworzyć nowy oddział, wykonaj następujące czynności:

git commit -m "your commit message"
git checkout -b new_branch

Następnie potencjalnie chcesz połączyć ten nowy oddział z innymi oddziałami. Zawsze pomocne jest polecenie git „pies” :

git log --all --decorate --oneline --graph
gebbissimo
źródło