Czy mogę odzyskać oddział po usunięciu go w Git?


1066

Jeśli uruchomię git branch -d XYZ, czy istnieje sposób na odzyskanie oddziału? Czy istnieje sposób na powrót, jakbym nie uruchomił polecenia usuwania gałęzi?


4
Naprawdę niesamowitą notatką na temat zaakceptowanej odpowiedzi jest to, że działa ona nawet wtedy, gdy gałąź została usunięta w oryginale! Właśnie odzyskałem kilka oddziałów, których nie miałem już lokalnie po przypadkowym usunięciu ich pochodzenia.
theblang

Odpowiedzi:


1955

Tak, powinieneś być w stanie zrobić git reflogi znaleźć SHA1 dla zatwierdzenia na końcu usuniętej gałęzi, a potem po prostu git checkout [sha]. A kiedy znajdziesz się w tym zatwierdzeniu, możesz po prostu git checkout -b [branchname]odtworzyć gałąź.


Podziękowania dla @Cascabel za tę wersję skróconą / jednowarstwową.

Możesz to zrobić w jednym kroku:

git checkout -b <branch> <sha>

477
Można to zrobić w jednym kroku: git checkout -b <branch> <sha>.
Cascabel,

200
Szybka wskazówka - jeśli właśnie usunąłeś gałąź, zobaczysz coś takiego w swoim terminalu - „Usunięto gałąź <twoja- gałąź> (był <sha>)”. A potem jest to bardzo łatwe - po prostu użyj tego <sha>. Np. Jak wspomniano powyżej -git checkout -b <branch> <sha>
Snowcrash

6
tak, po prostu przewiń w górę w swoim terminalu (chyba że zrobiłeś CMD+K)
neaumusic

42
Użyj, git reflog --no-abbrevaby zobaczyć pełne, <sha>które są domyślnie skracane.
jkulak

5
Dla każdego takiego jak ja, który miał problem ze znalezieniem sha usuniętej gałęzi: byłem w stanie git checkout remotes/origin/deleted_branch.
Jeff Irwin,

161

W większości przypadków nieosiągalne zatwierdzenia znajdują się w rejestrze. Więc pierwszą rzeczą jest, aby spróbować spojrzeć na reflog używając polecenia git reflog(które wyświetlają reflog dla HEAD).

Być może czymś łatwiejszym, jeśli zatwierdzenie było częścią jeszcze istniejącej gałęzi, jest użycie polecenia git reflog name-of-my-branch. Działa również z pilotem, na przykład, jeśli wymusiłeś push (dodatkowa rada: zawsze wolisz, git push --force-with-leaseaby lepiej zapobiegać błędom i jest łatwiejsza do odzyskania).


Jeśli twoje zatwierdzenia nie znajdują się w twoim logu (być może dlatego, że zostały usunięte przez narzędzie innej firmy, które nie zapisują w logu), udało mi się odzyskać gałąź, resetując moją gałąź do sha zatwierdzenia znalezionego za pomocą takiego polecenia (to tworzy plik ze wszystkimi wiszącymi zatwierdzeniami):

git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

Jeśli powinieneś użyć go więcej niż jeden raz (lub chcesz go gdzieś zapisać), możesz również utworzyć alias za pomocą tego polecenia ...

git config --global alias.rescue '!git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt'

i używaj go z git rescue

Aby zbadać znalezione zatwierdzenia, możesz wyświetlić każde zatwierdzenie za pomocą niektórych poleceń, aby je przejrzeć.

Aby wyświetlić metadane zatwierdzenia (autor, data utworzenia i komunikat zatwierdzenia):

git cat-file -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Aby zobaczyć także różnice:

git log -p 48540dfa438ad8e442b18e57a5a255c0ecad0560

Po znalezieniu zatwierdzenia utwórz gałąź tego zatwierdzenia za pomocą:

git branch commit_rescued 48540dfa438ad8e442b18e57a5a255c0ecad0560

Dla tych, które są w systemie Windows i lubią GUI, możesz łatwo odzyskać zatwierdzenia (a także niezaangażowane pliki etapowe) za pomocą GitExtensions , używając funkcji Repository=> Git maintenance=>Recover lost objects...


Usunięto podobne polecenie, aby łatwo odzyskać pliki przemieszczane: https://stackoverflow.com/a/58853981/717372


2
Ogromna pomoc. Miałem zagubione zatwierdzenie, którego nigdy nie było w moim lokalnym repozytorium. Pierwsze polecenie, które tam masz, pomogło mi znaleźć je na serwerze. +1
Sean Adkinson

1
ten alias ratunkowy git jest darem niebios !!! Dziękuję bardzo za wkład!
72A12F4E

2
Uratowałeś mi życie.
Jed Lynch,

Odpowiedź Patricka Koorevaara pomogła mi, ponieważ nie znam moich ostatnio usuniętych rozgałęzionych zatwierdzeń <sha>.
Monir Khan

@ Monir-Khan And? Co powinienem wyciągnąć? Odpowiedź Patricka jest tylko kopią / wklejeniem mojego polecenia (z błędem: zapomniał filtrować według zatwierdzeń) ...
Philippe

45

Jeśli chcesz użyć GUI, możesz wykonać całą operację za pomocą gitk.

gitk --reflog

Umożliwi to przeglądanie historii zatwierdzeń oddziału, tak jakby oddział nie został usunięty. Teraz wystarczy kliknąć prawym przyciskiem myszy najnowsze zatwierdzenie w gałęzi i wybrać opcję menu Create new branch.


28

Najlepiej ocenione rozwiązanie ma więcej niż wymagane:

git checkout <sha>
git checkout -b <branch>

lub

git checkout -b <branch> <sha>

przenieś Cię do nowego oddziału wraz ze wszystkimi ostatnimi zmianami, które mogłeś zapomnieć. To może nie być twoja intencja, szczególnie w „trybie paniki” po utracie gałęzi.

Bardziej przejrzystym (i prostszym) rozwiązaniem wydaje się być jedno-liniowy (po znalezieniu <sha>z git reflog):

git branch <branch> <sha>

Teraz nie ma to wpływu ani na twoją obecną gałąź, ani na nieprzewidziane zmiany. Zamiast tego zostanie utworzony tylko nowy oddział aż do <sha>.

Jeśli nie jest to wskazówka, nadal będzie działać, a otrzymasz krótszą gałąź, a następnie możesz ponowić próbę z nową <sha>i nową nazwą gałęzi, dopóki nie uzyskasz poprawności.

Wreszcie możesz zmienić nazwę pomyślnie przywróconej gałęzi na jej nazwę lub cokolwiek innego:

git branch -m <restored branch> <final branch>

Nie trzeba dodawać, że kluczem do sukcesu było znalezienie odpowiedniego zatwierdzenia <sha>, więc mądrze nazwij swoje zobowiązania :)


14

Dodanie do odpowiedzi tfe : istnieje również skrypt git-resurrect.sh w contrib/obszarze źródeł Git (w repozytorium git.git), który może ci pomóc.

git-resurrect <name>próbuje znaleźć ślady zwanego wierzchołkiem gałęzi <name>i próbuje go wskrzesić. Obecnie reflog jest przeszukiwany pod kątem komunikatów kasowych, a -rtakże korespondencji seryjnej. Za pomocą -mi -t, historia wszystkich referencji jest skanowana w celu Merge <name> into other/ Merge <other> into <name>(odpowiednio) zatwierdzania tematów, co jest raczej powolne, ale pozwala wskrzesić gałęzie tematyczne innych osób.


1
Teraz działało to dla mnie, chociaż musiałem dodać / usr / lib / git-core / do mojej PATH. Ale nie dokonał cudu, na który
liczyłem

10

Użyłem następujących poleceń, aby znaleźć i odzyskać usuniętą gałąź. Pierwsze kroki pochodzą z opisu gcb.

$ git fsck --full --no-reflogs --unreachable --lost-found > lost
$ cat lost | cut -d\  -f3 > commits
$ cat commits | xargs -n 1 git log -n 1 --pretty=oneline

Teraz poszukaj identyfikatora git commit (GIT-SHA) na podstawie komentarzy zatwierdzenia i użyj go w poniższym poleceniu. Zapoznaj się z nowym oddziałem o nazwie NEW-BRANCH z wcześniej znalezionym GIT-SHA:

$ git checkout -b NEW-BRANCH GIT-SHA

Dziękuję Ci bardzo. Trochę czasu zajęło wyszukanie nazwy, ale czas był tego wart. Jeśli istnieje sposób na przeszukanie łańcucha komunikatów zatwierdzenia, byłoby znacznie lepiej.
Monir Khan

9

Jeśli nie masz dziennika, np. ponieważ pracujesz w czystym repozytorium, w którym nie włączono ponownego rejestrowania, a zatwierdzenie, które chcesz odzyskać, zostało niedawno utworzone, inną opcją jest znalezienie ostatnio utworzonych obiektów zatwierdzenia i przejrzenie ich.

Z poziomu .git/objectskatalogu uruchom:

find . -ctime -12h -type f | sed 's/[./]//g' | git cat-file --batch-check | grep commit

Znajduje wszystkie obiekty (zatwierdzenia, pliki, tagi itp.) Utworzone w ciągu ostatnich 12 godzin i filtruje je, aby wyświetlać tylko zatwierdzenia. Sprawdzenie ich jest wtedy szybkim procesem.

Najpierw jednak spróbuję skryptu git-ressurect.sh wspomnianego w odpowiedzi Jakuba .


1
Fajny alternatywny pomysł! Twoje polecenie generuje jednak błąd. Problem dotyczy części „12h” (właściwie „h”). Gdy usunąłem „h”, zadziałało dobrze. Od man find: „-ctime n - Status pliku został ostatnio zmieniony n * 24 godziny temu.” Dlatego też powinniśmy zmienić 12 na 0,5, aby uzyskać oczekiwane zachowanie z ostatnich 12 godzin.
pagliuca

1
Używam tutaj OS X 10.8, więc powyższe flagi „znajdź” zależą od wersji, którą dostarcza.
Robert Knight

1
Tak, na pewno problem dotyczy wersji! Dlatego głosowałem na twoją odpowiedź na pierwszym miejscu! Właśnie skomentowałem, aby ludzie zdali sobie sprawę, że parametry mogą być inne.
pagliuca

9

Dla użytkowników GitHub bez zainstalowanego Git:

Jeśli chcesz przywrócić go ze strony GitHub , możesz użyć jego interfejsu API, aby uzyskać listę zdarzeń związanych z repo:

Pierwszy

  • znajdź te SHA (zatwierdzaj skróty):

    curl -i https://api.github.com/repos/PublicUser/PublicRepo/events

    ... lub w przypadku prywatnych repozytoriów:

    curl -su YourUserName https://api.github.com/repos/YourUserName/YourProject/events

    (zostanie wyświetlony monit o podanie hasła GitHub)

    • (Jeśli repo wymaga uwierzytelnienia dwuskładnikowego, zobacz komentarze do tej odpowiedzi poniżej.)

Kolejny

  • przejdź do GitHub i utwórz nową gałąź tymczasową, która zostanie na zawsze usunięta ( najlepiej Chrome ).

   • Idź do oddziałów i usuń ten.

   •   Na tej samej stronie, bez ponownego ładowania , otwórz DevTools, panel Sieć. Teraz przygotuj ...

   • Kliknij przywróć. Zauważysz nową „linię”. Kliknij go prawym przyciskiem myszy i wybierz „Kopiuj jako cURL” i zapisz ten tekst w edytorze.

   • Dołącz do końca kopiowanego wiersza kodu, to jedno: -H "Cookie=".

Powinieneś teraz uzyskać coś takiego:

    curl 'https://github.com/UserName/ProjectName/branches?branch=BranchSHA&name=BranchName' -H 'Cookie:' -H 'Origin: https://github.com' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US' -H 'User-Agent: User-Agent' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Accept: */*' -H 'Referer: https://github.com/UserName/ProjectName/branches' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --data 'utf8=%E2%9C%93&authenticity_token=token' --compressed

Ostatni krok

  • zamień „BranchSHA” na skrót SHA i BranchName na pożądaną nazwę (BTW, to świetny hack, aby zmienić nazwę gałęzi z sieci). Jeśli nie byłeś zbyt wolny, i tak musisz złożyć wniosek. Na przykład po prostu skopiuj-wklej do terminala.

PS

Zdaję sobie sprawę, że to nie może być „najprostsze rozwiązanie” lub „właściwe” rozwiązanie, ale jest oferowane w przypadku, gdy ktoś uzna to za przydatne.


1
Powyższe jest jednym z nielicznych, na którym nie można polegać git reflogi dlatego było przydatne na przykład, gdy usunięto zdalną gałąź i utracono dostęp do komputera, z którego zostało zrobione, więc nic użytecznego nie można uzyskać reflog. Uwaga przy użyciu uwierzytelniania OAuth lub dwuskładnikowego na Githubcurl polecenie staje się w postaci: curl -u username:token https://api.github.com/userlubcurl -H "Authorization: token TOKEN" https://api.github.com/repos/USER_OR_ORG_NAME/REPO_NAME/events
TT--

@ TT-- wow, cieszę się, że to pomogło! i dziękuję za Twój wkład dotyczący tokena uwierzytelniającego :)
Maxim Mazurok

8

Z mojego zrozumienia, czy gałąź, która ma zostać usunięta, może być osiągnięta przez inną gałąź, możesz ją bezpiecznie usunąć za pomocą

git branch -d [branch]

a twoja praca nie jest stracona. Pamiętaj, że gałąź nie jest migawką, ale wskaźnikiem do jednego. Więc kiedy usuwasz gałąź, usuwasz wskaźnik.

Nie stracisz nawet pracy, jeśli usuniesz gałąź, do której nie może dotrzeć żaden inny. Oczywiście nie będzie to tak łatwe, jak sprawdzenie skrótu, ale nadal możesz to zrobić. Dlatego Git nie może usunąć gałęzi, do której nie można uzyskać dostępu za pomocą -d. Zamiast tego musisz użyć

git branch -D [branch]

To część obowiązkowego filmu Scotta Chakona na temat Gita. Sprawdź minutę 58:00, kiedy mówi o oddziałach i jak je usunąć.

Wprowadzenie do Git ze Scott Chacon z GitHub


7
Jak to pomaga odpowiedzieć na pytanie?
Dmitri Zaitsev

6
Mówienie pytającemu, że gałęzie nie zawierają treści, ale w rzeczywistości są wskaźnikami. Nie musisz bać się usuwania gałęzi. Możesz tworzyć nowe, wskazujące na to samo zatwierdzenie, co usunięte ... Wow! Nadal pamiętam, kiedy zadałem to pytanie. Dobre czasy z powrotem do 2012 roku!
fabiopagoti

1
Musiałem przewinąć trzy ekrany do AT LAST, aby znaleźć odpowiedź, która rozwiązuje problem: usunięcie gałęzi usuwa zwykły wskaźnik. Brak sytuacji utraty danych, jedyne, co można odzyskać, to dokąd to wskazywało. Odpowiedzi, które trafiają bezpośrednio, reflogto po prostu przesada.
RomainValeri

5

Wykonaj to wszystko lokalnie i upewnij się, że Twoje repo jest w pożądanym stanie, zanim przejdziesz do Bitbucket Cloud. Dobrym pomysłem może być również sklonowanie bieżącego repozytorium i przetestowanie tych rozwiązań w pierwszej kolejności.

  1. Jeśli właśnie usunąłeś gałąź, zobaczysz coś takiego w swoim terminalu:
    Deleted branch <your-branch> (was <sha>)

2. Aby przywrócić gałąź, użyj:

    git checkout -b <branch> <sha>

Jeśli nie znasz „sha” z czubka głowy, możesz:

  1. Znajdź „sha” dla zatwierdzenia na końcu usuniętej gałęzi, używając:
    git reflog
  1. Aby przywrócić gałąź, użyj:
    git checkout -b <branch> <sha>

Jeśli twoich zatwierdzeń nie ma w twoim logu:

  1. Możesz spróbować odzyskać gałąź, resetując gałąź do sha zatwierdzenia znalezionego za pomocą polecenia takiego jak:
    git fsck --full --no-reflogs --unreachable --lost-found | grep commit | cut -d\  -f3 | xargs -n 1 git log -n 1 --pretty=oneline > .git/lost-found.txt

2. Następnie możesz wyświetlić każde zatwierdzenie, używając jednego z tych:

    git log -p <commit>
    git cat-file -p <commit>

4

Aby odzyskać usuniętą gałąź, najpierw przejrzyj historię ponownego logowania,

git reflog -n 60

Gdzie n oznacza ostatnie n zatwierdzeń. Następnie znajdź odpowiednią głowę i utwórz gałąź za pomocą tej głowy.

git branch testbranch HEAD@{30}

4

Odwróciłem gałąź od pilota, aby spróbować wyczyścić kilka niepotrzebnych zmian i zamierzałem wybrać właściwe, które chciałem. Oczywiście, że źle napisałem SHA ...

Oto jak je znalazłem (głównie łatwiejszy interfejs / interakcja na podstawie odpowiedzi tutaj):

Najpierw wygeneruj listę luźnych zatwierdzeń w swoim dzienniku. Zrób to jak najszybciej i przestań działać, ponieważ mogą zostać zrzucone przez moduł wyrzucający śmieci.

git fsck --full --no-reflogs --unreachable --lost-found > lost

Spowoduje to utworzenie lostpliku ze wszystkimi zatwierdzeniami, które będziesz musiał obejrzeć. Aby uprościć nasze życie, odetnijmy od niego tylko SHA:

cat lost | cut -d\  -f3 > commits

Teraz masz commitsplik ze wszystkimi zobowiązaniami, które musisz sprawdzić.

Zakładając, że używasz Bash, ostatni krok:

for c in `cat commits`; do  git show $c; read; done

Spowoduje to wyświetlenie różnic i zatwierdzenie informacji dla każdego z nich. I czekaj, aż naciśniesz Enter. Teraz zapisz wszystkie te, które chcesz, a następnie wybierz je. Po zakończeniu, po prostu Ctrl-C to.



1

Najpierw przejdź do git i przenieś do swojego projektu w następujący sposób:

cd android studio project
cd Myproject
then type :
git reflog

Wszyscy macie listę zmian, a numer referencyjny weź numer referencyjny, a następnie kasy
z Android Studio lub z Git Betcha. innym rozwiązaniem weź numer referencyjny i przejdź do Android Studio, kliknij gałęzie git w dół, a następnie kliknij tag kasy lub rewizję obok numeru referencyjnego, a następnie lol masz gałęzie.


1

Dodając do odpowiedzi tfe, możesz odzyskać dzięki wspomnianemu procesowi, chyba że jego zatwierdzenia nie są usuwane. Git gałąź jest po prostu wskaźnikiem do konkretnego zatwierdzenia w drzewie zatwierdzeń. Ale jeśli usuniesz wskaźnik, a zatwierdzenia w tej gałęzi nie zostaną scalone z innymi istniejącymi gałęziami, git traktuje go jako wiszące zatwierdzenia i usuwa je podczas wyrzucania elementów bezużytecznych, które może okresowo uruchamiać się automatycznie.

Jeśli twoja gałąź nie została scalona z istniejącą gałęzią, a jeśli została wyrzucona śmieci, stracisz wszystkie zatwierdzenia aż do momentu, w którym gałąź została rozwidlona z istniejącej gałęzi.


1

Powiązany problem: Przyszedłem na tę stronę po wyszukiwaniu hasła „jak się dowiedzieć, jakie skasowane gałęzie”.

Usuwając wiele starych gałęzi, czułem, że omyłkowo usunąłem jedną z nowszych gałęzi, ale nie znałem nazwy, aby ją odzyskać.

Aby wiedzieć, które gałęzie zostały ostatnio usunięte, wykonaj następujące czynności:

Jeśli przejdziesz do adresu URL Git, który będzie wyglądał mniej więcej tak:

https://your-website-name/orgs/your-org-name/dashboard

Następnie możesz zobaczyć kanał, z którego usunięto, przez kogo, w niedawnej przeszłości.


Pewnie. Powyższa odpowiedź dotyczy GitHub. GitHub zainstalowaliśmy lokalnie. Dziękuję za pytanie.
Manohar Reddy Poreddy

1

Zrobiłem to na komputerze, który usunąłem gałąź:

git reflog

odpowiedź:

74b2383 (develope) HEAD@{1}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{2}: checkout: moving from develope to master
74b2383 (develope) HEAD@{3}: checkout: moving from master to develope
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{4}: reset: moving to HEAD
40ef328 (HEAD -> master, origin/master, origin/HEAD) HEAD@{5}: clone: from http://LOCALGITSERVER/myBigProject/Android.git

i pobieram gałąź za pomocą tego polecenia:

git checkout -b newBranchName 74b2383


0

Samo użycie git reflognie zwróciło shami. Tylko commit id(który ma 8 znaków, a sha jest znacznie dłuższy)

Więc użyłem git reflog --no-abbrev

A następnie wykonaj to samo, co wspomniano powyżej: git checkout -b <branch> <sha>


zawsze możesz użyć skrótu 8 sha, nie musisz używać pełnego sha
Michael Dreher

0

JEŻELI używasz VSCode ... i zsynchronizowałeś swój oddział z serwerem w pewnym momencie przed jego usunięciem ...

Zauważ, że usunięcie gałęzi git usuwa tylko kopię lokalną, a nie kopię na serwerze. Najpierw w panelu Git (ikona git na lewym pasku narzędzi) przejrzyj gałęzie i sprawdź, czy gałąź wciąż tam jest pod „origin / two_branch_name”. Jeśli tak, po prostu wybierz to i powinieneś odzyskać swój kod (sugeruj, aby natychmiast skopiować / wkleić / zapisać go lokalnie w innym miejscu).

Jeśli nie widziałeś „origin / your_branch_name”, zainstaluj rozszerzenie GitLens. Pozwala to wizualnie przeszukiwać repozytoria serwerów i zlokalizować zsynchronizowaną kopię z serwerem. Jeśli masz wiele repozytoriów, pamiętaj, że może być konieczne otwarcie co najmniej jednego pliku z żądanego repozytorium, aby repozytorium pojawiło się w GitLens. Następnie:

  1. Otwórz panel GitLens

  2. Rozwiń repozytorium

  3. Powinieneś zobaczyć listę kategorii: Oddziały / Współautorzy / Piloty / Skrytki / itp

YourLostTreasure powinien znaleźć się w „Oddziałach” lub ewentualnie w „Pilocie -> Początki”. Mamy nadzieję, że zobaczysz gałąź o pożądanej nazwie - jeśli ją rozwiniesz, powinieneś zobaczyć pliki, które zmieniłeś w tej gałęzi. Kliknij dwukrotnie nazwy plików, aby je otworzyć, i natychmiast wykonaj kopię zapasową tego kodu.

Jeśli nie widzisz od razu swojej zagubionej gałęzi, rozejrzyj się, a jeśli znajdziesz coś obiecującego, natychmiast otwórz ją i pobierz kod. Musiałem trochę się rozejrzeć, aż znalazłem TheGoldenBranch, a nawet wtedy w kodzie brakowało ostatniego jednego lub dwóch zapisów (być może dlatego, że nie udało mi się zsynchronizować z serwerem przed próbą scalenia oddziału, ale przypadkowo kliknięcia- Usuń oddział). Moje poszukiwania zostały niepotrzebnie wydłużone, ponieważ kiedy pierwszy raz znalazłem gałąź, nie byłem do końca pewien, czy nazwa jest poprawna, więc szukałem dalej i zajęło mi to trochę czasu, aby znaleźć tę pierwszą gałąź. (Tak więc Carpe Carpum, a następnie szukaj dalej.)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.