Jak mogę przenieść HEAD z powrotem do poprzedniej lokalizacji? (Odłączona głowa) i Cofnij zatwierdza

179

W Git próbowałem zrobić squash commit, łącząc się z innym oddziałem, a następnie resetując HEADsię do poprzedniego miejsca poprzez:

git reset origin/master

Ale muszę wyjść z tego. Jak mogę przenieść HEAD z powrotem do poprzedniej lokalizacji?

Mam fragment SHA-1 ( 23b6772) zatwierdzenia, do którego muszę go przenieść. Jak mogę wrócić do tego zatwierdzenia?

opóźnienie
źródło
12
HEAD jest tylko wskaźnikiem do twojej bieżącej lokalizacji (lub rewizji, by być precyzyjnym). git checkout 23b6772powinieneś zrobić.
Jarosław Administrator
1
@YaroslavAdmin nr powinien nie . Bezpośrednie sprawdzanie zatwierdzenia jest przyczyną odłączenia stanu HEAD (ponieważ gałęzi zdalnego śledzenia nie można samodzielnie sprawdzić i automatycznie odraczają zatwierdzenie, na które wskazują, gdy próbujesz to zrobić, tak jak zrobił to OP). Przepraszamy również za nekromancję komentarz :-) Mam nadzieję, że początkowy problem został już rozwiązany ...
RomainValeri

Odpowiedzi:

397

Przed odpowiedzią dodajmy tło, wyjaśniając, co to HEADjest.

First of all what is HEAD?

HEADjest po prostu odniesieniem do bieżącego zatwierdzenia (najnowszego) w bieżącej gałęzi.
W HEADdanym momencie może być tylko jeden (wyłączając git worktree).

Zawartość HEADjest przechowywana w środku .git/HEADi zawiera 40 bajtów SHA-1 bieżącego zatwierdzenia.


detached HEAD

Jeśli nie korzystasz z ostatniego zatwierdzenia - oznacza HEADto, że nazywa się to wcześniejszym zatwierdzeniem w historii detached HEAD.

Wpisz opis zdjęcia tutaj

W wierszu poleceń będzie to wyglądać tak - SHA-1 zamiast nazwy gałęzi, ponieważ HEADnie wskazuje ona końcówki bieżącej gałęzi:

Wpisz opis zdjęcia tutaj

Wpisz opis zdjęcia tutaj


Kilka opcji odzyskiwania po odłączeniu HEAD:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Spowoduje to pobranie nowej gałęzi wskazującej żądany zatwierdzenie.
To polecenie pobierze do danego zatwierdzenia.
W tym momencie możesz utworzyć gałąź i od tego momentu zacząć pracować.

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Zawsze możesz również użyć reflog.
git reflog wyświetli każdą zmianę, która zaktualizowała HEADi sprawdzenie żądanego wpisu ponownego logowania spowoduje HEADpowrót do tego zatwierdzenia.

Za każdym razem, gdy HEAD zostanie zmodyfikowany, pojawi się nowy wpis w reflog

git reflog
git checkout HEAD@{...}

Spowoduje to powrót do żądanego zatwierdzenia

Wpisz opis zdjęcia tutaj


git reset --hard <commit_id>

„Przenieś” HEAD z powrotem do żądanego zatwierdzenia.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Uwaga: ( od wersji Git 2.7 ) możesz również korzystać z nich git rebase --no-autostash.

git revert <sha-1>

„Cofnij” podany zakres zatwierdzania lub zatwierdzania.
Polecenie reset spowoduje „cofnięcie” wszelkich zmian dokonanych w danym zatwierdzeniu.
Nowe zatwierdzenie z łatką cofania zostanie zatwierdzone, podczas gdy oryginalne zatwierdzenie pozostanie również w historii.

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Ten schemat ilustruje, które polecenie robi co.
Jak widać, reset && checkoutzmodyfikuj HEAD.

Wpisz opis zdjęcia tutaj

CodeWizard
źródło
Jeśli nie korzystasz z ostatniego zatwierdzenia - co oznacza, że ​​HEAD wskazuje na wcześniejsze zatwierdzenie w historii, nazywa się HEAD odłączonym, chyba że wcześniejsze zatwierdzenie w historii jest wierzchołkiem innej gałęzi. Z mojego doświadczenia można powiedzieć, że jesteś odłączony, jeśli HEAD nie wskazuje na zatwierdzenie, na które wskazuje również dowolna gałąź. Nie dotyczy to tagów.
Tim
Możesz być odłączony HEAD i jednocześnie mieć gałąź z tym samym zatwierdzeniem co HEAD tej gałęzi. Nie rozumiem twojego komentarza
CodeWizard
3
Mam problemy z korzystaniem ze znaczników kodu wbudowanego dla nagłówków :)
jub0bs
Nie można znaleźć lepszego sposobu na podkreślenie tego. nie krępuj się edytować. Serdecznie zapraszamy
CodeWizard,
22

Robić

git reset 23b6772

Aby sprawdzić, czy jesteś na właściwej pozycji:

git status

Zobaczysz coś

On master master Twój oddział stoi za „origin / master” o 17 zatwierdzeń i może być szybko przekazywany.

Następnie przepisz historię na pilocie, aby odzwierciedlić zmianę:

git push --force-with-lease // a useful command @oktober mentions in comments
osobliwy
źródło
1
WYJĄTKOWO OSTROŻNIE za pomocą git push --force. W wielu sytuacjach sprawi, że staniesz się przez jakiś czas najmniej popularną osobą w zespole ....
Kay V
aby dodać do powyższej notatki, właśnie natknąłem się na ten cytat pod adresem about.gitlab.com/blog/2014/11/26/keeping-your-code-protected i musiałem go dodać: „Pojedyncze polecenie git push --force może z łatwością zrujnować dzień wielu ludziom: repozytoria [186 Jenkins] mają przewinięte głowy oddziałów, aby wskazywały na starsze zatwierdzenia, a w efekcie nowsze zatwierdzenia zostały niewłaściwie umieszczone po złym git-push ”. - bardzo niepopularny programista ....
Kay V
2
@KayV spójrz na git push --force-with-lease(artykuł Thoughtbot : thinkbot.com/blog/git-push-force-with-lease )
października
1
Przydatna flaga, @oktober i dobry artykuł. Dzięki za dodanie go tutaj i pingowanie mnie o tym.
Kay V
1
Dziękuję Ci! pomogło mi to zrobić złe połączenie. ponieważ fuzje nie reagują w taki sam sposób, revertjak zobowiązania, znalazłem się w niezwykle trudnej sytuacji. force-with-leasedał mi pewność, że przepisałem historię git oddziału bez wpływu na pracę innych ludzi. Brawo!
anon58192932
11

Najszybsze możliwe rozwiązanie (tylko 1 krok)

Posługiwać się git checkout -

Widać Switched to branch <branch_name>. Potwierdź, że to gałąź, którą chcesz.


Krótkie wyjaśnienie: to polecenie spowoduje powrót HEAD z powrotem do ostatniej pozycji. Uwaga na temat wyników na końcu tej odpowiedzi.


Mnemoniczny: takie podejście przypomina cd -powrót do wcześniej odwiedzonego katalogu. Składnia i odpowiednie przypadki są całkiem dobre (np. Jest to przydatne, gdy naprawdę chcesz, aby HEAD powrócił tam, gdzie był).


Bardziej metodyczne rozwiązanie (2 kroki, ale niezapomniane)

Szybkie podejście rozwiązuje pytanie PO. Ale co, jeśli twoja sytuacja jest nieco inna: powiedz, że uruchomiłeś ponownie Bash, a następnie odkryłeś, że HEAD jest odłączony. W takim przypadku oto 2 proste, łatwe do zapamiętania kroki.

1. Wybierz potrzebny oddział

Posługiwać się git branch -v

Zobaczysz listę istniejących lokalnych oddziałów. Chwyć nazwę oddziału, która odpowiada Twoim potrzebom.

2. Przenieś na nią HEAD

Posługiwać się git checkout <branch_name>

Widać Switched to branch <branch_name>. Sukces!


Wyniki

Za pomocą dowolnej z tych metod możesz teraz kontynuować dodawanie i zatwierdzanie swojej pracy jak poprzednio: kolejne zmiany będą śledzone <branch_name>.

Zauważ, że oba git checkout -i git checkout <branch_name>podadzą dodatkowe instrukcje, jeśli dokonałeś zmian podczas odłączenia HEAD.

Kay V.
źródło
To nie działa, ponieważ jeśli to zrobię (zakładając, że 8acc968 to HEAD ~ 2), git checkout 8acc968to git branch -vma MyBranchna poniższej liście ... ale potem git checkout MyBranchusuwa moje komentarze.
amuliar
Cześć @amuliar - git checkout 8acc968sprawdzi zatwierdzenie, a nie oddział. Jeśli MyBranchmasz zatwierdzenia, spróbuj git checkout MyBranch. Jeśli nie zawiera zmian w zatwierdzeniu 8acc968, konieczne będzie scalenie tych zmian po sprawdzeniu gałęzi.
Kay V
Dziękuję za odpowiedź! Widziałem git checkoutpoprzednie zatwierdzenie i chciałem wrócić do ostatniego zatwierdzenia. Ale bez najnowszego skrótu zatwierdzenia byłem prawie zagubiony. To rozwiązanie jest idealne dla mojej sytuacji!
zyy
4

Pytanie można odczytać jako:

Byłem w stanie z oderwanego- HEADu 23b6772i wpisany git reset origin/master(bo chciałem squash). Teraz zmieniłem zdanie, jak wrócić do HEADbycia 23b6772?

Prosta odpowiedź brzmi: git reset 23b6772

Ale uderzyłem w to pytanie, ponieważ miałem dość pisania na maszynie (kopiowanie i wklejanie) skrótów zatwierdzania lub ich skrótów za każdym razem, gdy chciałem odwoływać się do poprzedniego HEADi byłem w Google, aby sprawdzić, czy istnieje jakiś skrót.

Okazuje się, że jest!

git reset -(lub w moim przypadku git cherry-pick -)

Który nawiasem mówiąc był taki sam jak cd -powrót do poprzedniego bieżącego katalogu w * nix! Hurra, nauczyłem się dwóch rzeczy za pomocą jednego kamienia.

antak
źródło
0

Po uruchomieniu polecenia git checkout commit_idHEAD został odłączony, 13ca5593d(say commit-id)a gałąź będzie dłużej dostępna.

Wróć do poprzedniej lokalizacji, uruchom komendę krok po kroku -

  1. git pull origin branch_name (powiedz mistrz)
  2. git checkout branch_name
  3. git pull origin branch_name

Powrócisz do poprzedniej lokalizacji ze zaktualizowanym zatwierdzeniem ze zdalnego repozytorium.

Deepak Kumar
źródło
0

Dzisiaj przez pomyłkę sprawdziłem zatwierdzenie i zacząłem nad nim pracować, wprowadzając pewne zmiany w stanie odłączenia HEAD. Następnie wypychałem do zdalnej gałęzi za pomocą następującego polecenia:

git push origin HEAD: <My-remote-branch>

Następnie

git checkout <My-remote-branch>

Następnie

git pull

W końcu dostałem wszystkie moje zmiany w moim oddziale, które wprowadziłem w odłączaniu HEAD.

Zaid Mirza
źródło
0

To może nie być rozwiązanie techniczne, ale działa. (jeśli ktoś z twojego członka drużyny ma ten sam oddział w lokalnym)

Załóżmy, że nazwa oddziału to gałąź-xxx .

Kroki do rozwiązania:

  • Nie rób aktualizacji ani nie ciągnij - nic
  • Wystarczy utworzyć nową gałąź ( gałąź-rrr ) z gałęzi-xxx na swoim komputerze
  • To wszystko, wszystkie istniejące zmiany będą w tej nowej gałęzi ( oddział-rrr ). Możesz kontynuować pracę w tym oddziale.

Uwaga: Ponownie, nie jest to rozwiązanie techniczne, ale na pewno pomoże.

Sathish Kumar
źródło