Jak odzyskać upuszczony towar w Git?

Często używam git stash i git stash pop do zapisywania i przywracania zmian w moim roboczym drzewie. Wczoraj miałem kilka zmian w moim drzewie roboczym, które schowałem i pękłem, a potem zrobiłem więcej zmian w moim drzewie roboczym. Chciałbym wrócić i przejrzeć wczorajsze Ukryte zmiany, ale git stash pop wydaje się usuwać wszystkie odniesienia do powiązanego commita.

Wiem, że jeśli używam git stash to .git/refs / stash zawiera odniesienie do zatwierdzenia użytego do utworzenia stash. Oraz .git/logs/refs / stash zawiera cały stash. Ale te odniesienia zniknęły po git stash pop. Wiem, że commit jest gdzieś w moim repozytorium, ale nie wiem, co to było.

Czy istnieje łatwy sposób na odzyskanie odniesienia do zmian w skrytce?

Zauważ, że nie jest to dla mnie dzisiaj krytyczne, ponieważ mam codzienne kopie zapasowe i mogę wrócić do wczorajszego roboczego drzewa, aby uzyskać moje zmiany. Pytam, bo musi być łatwiejszy sposób!

Author: Randall, 2008-09-18

19 answers

Jeśli dopiero co go uruchomiłeś, a terminal jest nadal otwarty, będziesz nadal mieć wartość skrótu wydrukowaną przez git stash pop na ekranie (Dzięki, Dolda).

W przeciwnym razie możesz go znaleźć używając tego dla Linuksa i Unixa:

git fsck --no-reflog | awk '/dangling commit/ {print $3}'

I Dla Windows:

git fsck --no-reflog | select-string 'dangling commit' | foreach { $bits = $_ -split ' '; echo $bits[2];}

To pokaże Ci wszystkie commity na końcu wykresu commitów, które nie są już powiązane z żadną gałęzią lub tagiem – każdy utracony commit, w tym każdy commit stash, który kiedykolwiek stworzyłeś, będzie gdzieś na tym wykresie.

Najprostszym sposobem na znalezienie żądanego commita stash jest prawdopodobnie przekazanie tej listy gitk:

gitk --all $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' )

Spowoduje to uruchomienie przeglądarki repozytorium pokazującej każdy commit w repozytorium kiedykolwiek, niezależnie od tego, czy jest osiągalny, czy nie.

Możesz tam zastąpić gitk czymś w rodzaju git log --graph --oneline --decorate, jeśli wolisz ładny wykres na konsoli niż oddzielną aplikację GUI.

Aby wykryć commity stash, poszukaj komunikatów commit ta forma:

WIP on some Branch: commithash niektóre stare commit wiadomość

Notatka: wiadomość zatwierdzająca będzie miała taką postać (zaczynającą się od "WIP on") tylko wtedy, gdy nie podałeś wiadomości, kiedy to zrobiłeś git stash.

Gdy już znasz hash zatwierdzania, możesz zastosować go jako skrytkę:

git stash apply $stash_hash

Lub możesz użyć menu kontekstowego w gitk, aby utworzyć gałęzie dla wszelkich nieosiągalnych commitów, które Cię interesują. Po tym, można zrobić cokolwiek chcesz z nimi z wszystkich normalnych narzędzi. Kiedy skończysz, po prostu zdmuchnij te gałęzie ponownie.

 2195
Author: Aristotle Pagaltzis,
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
2017-05-23 12:10:54

Jeśli nie zamknąłeś terminala, po prostu spójrz na wyjście z git stash pop i będziesz miał ID obiektu upuszczonego schowka. Normalnie wygląda to tak:

$ git stash pop
[...]
Dropped refs/stash@{0} (2ca03e22256be97f9e40f08e6d6773c7d41dbfd1)

(zauważ, że git stash drop również tworzy tę samą linię.)

Aby odzyskać ten towar, po prostu biegnij git branch tmp 2cae03e, a dostaniesz go jako gałąź. Aby przekonwertować to na skrytkę, Uruchom:

git stash apply tmp
git stash

Posiadanie go jako gałęzi pozwala również na swobodne manipulowanie nim; na przykład, aby je wybrać lub połączyć.

 617
Author: Dolda2000,
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
2012-02-22 23:45:33

Chciałem tylko wspomnieć o tym dodatku do przyjętego rozwiązania. Nie było to dla mnie oczywiste za pierwszym razem, kiedy próbowałem tej metody (być może powinno być), ale aby zastosować stash z wartości hash, po prostu użyj "git stash apply": {]}

$ git stash apply ad38abbf76e26c803b27a6079348192d32f52219

Kiedy byłem nowy w git, nie było to dla mnie jasne i próbowałem różnych kombinacji "git show", "Git apply", "patch", itp.

 238
Author: Wade,
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
2009-03-03 20:28:51

Właśnie skonstruowałem polecenie, które pomogło mi znaleźć commit zaginionego schowka:

for ref in `find .git/objects | sed -e 's#.git/objects/##' | grep / | tr -d /`; do if [ `git cat-file -t $ref` = "commit" ]; then git show --summary $ref; fi; done | less

Wyświetla listę wszystkich obiektów w .drzewo git / objects, lokalizuje te, które są typu commit, a następnie pokazuje podsumowanie każdego z nich. Od tego momentu była to tylko kwestia przejrzenia commitów w celu znalezienia odpowiedniego" WIP on work: 6a9bb2 "("work" to moja gałąź, 619bb2 to ostatni commit).

Zauważam, że jeśli użyję "git stash apply "zamiast" git stash pop " Nie będę miał tego problemu, a jeśli użyję" git stash save message " wtedy commit mógłby być łatwiejszy do znalezienia.

Update: z pomysłem Nathana, to staje się krótsze:

for ref in `git fsck --unreachable | grep commit | cut -d' ' -f3`; do git show --summary $ref; done | less
 69
Author: Greg Hewgill,
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
2008-09-18 02:10:13

Aby uzyskać listę stahów, które są nadal w Twoim repozytorium, ale nie są już dostępne:

git fsck --unreachable | grep commit | cut -d" " -f3 | xargs git log --merges --no-walk --grep=WIP

Jeśli podałeś tytuł skrytki, zastąp "WIP" w -grep=WIP na końcu polecenia częścią wiadomości, np. -grep=Tesselation.

Polecenie grepping dla "WIP", ponieważ domyślna wiadomość zatwierdzająca skrytkę ma postać WIP on mybranch: [previous-commit-hash] Message of the previous commit.

 64
Author: Senthil A Kumar,
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
2017-09-19 12:01:28

git fsck --unreachable | grep commit powinien pokazywać sha1, chociaż lista, którą zwraca, może być dość duża. git show <sha1> pokaże, czy jest to commit, którego chcesz.

git cherry-pick -m 1 <sha1> Scali commit do bieżącej gałęzi.

 37
Author: Nathan Jones,
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
2008-09-18 02:14:27

Jeśli chcesz uzupełnić zaginioną skrytkę, musisz najpierw znaleźć hash swojej zaginionej skrytki.

Jak Arystoteles Pagaltzis zasugerował git fsck powinno ci pomóc.

Osobiście używam mojego log-all aliasu, który pokazuje mi każdy commit (commity odzyskiwalne), aby mieć lepszy wgląd w sytuację :

git log --graph --decorate --pretty=oneline --abbrev-commit --all $(git fsck --no-reflogs | grep commit | cut -d' ' -f3)

Możesz zrobić jeszcze szybsze wyszukiwanie, jeśli szukasz tylko wiadomości "WIP on".

Gdy poznasz sha1, po prostu zmienisz swój magazyn skrytek, aby dodać Stary Schowek :

git update-ref refs/stash ed6721d

Prawdopodobnie wolisz mieć powiązaną wiadomość, więc -m

git update-ref -m "$(git log -1 --pretty=format:'%s' ed6721d)" refs/stash ed6721d

I będziesz nawet chciał użyć tego jako aliasu:

restash = !git update-ref -m $(git log -1 --pretty=format:'%s' $1) refs/stash $1
 23
Author: Colin Hebert,
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-01-09 22:18:52

Podobało mi się podejście Arystotelesa, ale nie podobało mi się używanie GITK... jak jestem przyzwyczajony do korzystania z GIT z linii poleceń.

Zamiast tego wziąłem zwisające commity i wysłałem kod do pliku DIFF do przejrzenia w moim edytorze kodu.

git show $( git fsck --no-reflog | awk '/dangling commit/ {print $3}' ) > ~/stash_recovery.diff

Teraz możesz załadować wynikowy plik diff / txt (jego w folderze domowym) do edytora txt i zobaczyć rzeczywisty kod i wynikowe SHA.

Następnie po prostu użyj

git stash apply ad38abbf76e26c803b27a6079348192d32f52219
 15
Author: Shaheen Ghiassy,
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
2013-01-07 20:17:34

W OSX z git v2.6.4, po prostu uruchomiłem Git stash Drop przypadkowo, potem znalazłem go przechodząc przez koryto poniżej kroków

Jeśli znasz nazwę skrytki to Użyj:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show | grep -B 6 -A 2 <name of the stash>

W Przeciwnym Razie znajdziesz ID z wyniku ręcznie za pomocą:

$ git fsck --unreachable | grep commit | cut -c 20- | xargs git show

Następnie, gdy znajdziesz commit-id, naciśnij git stash apply {commit-id}

Mam nadzieję, że to pomoże komuś szybko

 12
Author: Can Tecim,
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-11-01 09:57:53

Odpowiednik Windows PowerShell przy użyciu gitk:

gitk --all $(git fsck --no-reflog | Select-String "(dangling commit )(.*)" | %{ $_.Line.Split(' ')[2] })

Jest prawdopodobnie bardziej efektywny sposób, aby to zrobić w jednej rurze, ale to robi swoje.

 11
Author: emragins,
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-01-07 23:22:05

Chcę dodać do zaakceptowanego rozwiązania jeszcze jeden dobry sposób, aby przejść przez wszystkie zmiany, gdy albo nie masz dostępnego gitk lub nie ma x dla wyjścia.

git fsck --no-reflog | awk '/dangling commit/ {print $3}' > tmp_commits

for h in `cat tmp_commits`; do git show $h | less; done

Następnie otrzymasz wszystkie diffy dla tych hashów wyświetlane jeden po drugim. Naciśnij "q", aby przejść do następnego różnicowania.

 10
Author: Phil,
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
2013-01-04 12:32:19

Dlaczego ludzie zadają to pytanie? Bo jeszcze nie wiedzą ani nie rozumieją reflogu.

Większość odpowiedzi na to pytanie daje długie polecenia z opcjami, których prawie nikt nie zapamięta. Więc ludzie przychodzą na to pytanie i kopiują wklej to, co myślą, że potrzebują i zapominają o tym niemal natychmiast po tym.

Radzę wszystkim z tym pytaniem po prostu sprawdzić reflog (git reflog), niewiele więcej. Gdy zobaczysz listę wszystkich commitów, będzie ich sto sposoby, aby dowiedzieć się, jakiego commita szukasz i wybrać go lub utworzyć z niego gałąź. Podczas tego procesu dowiesz się o reflogu i użytecznych opcjach różnych podstawowych komend Gita.

 10
Author: RobbyD,
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-05-26 10:38:18

Zaakceptowana przez Arystotelesa odpowiedź pokaże wszystkie dostępne commity, w tym commity inne niż stash. Aby odfiltrować szum:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3

Obejmie to tylko commity, które mają dokładnie 3 nadrzędne commity (które będzie miał stash) i których wiadomość zawiera "WIP on".

Pamiętaj, że jeśli zapisałeś skrytkę z wiadomością (np. git stash save "My newly created stash"), to nadpisze to domyślne " WIP on..."wiadomość.

Możesz wyświetlić więcej informacji o każdym zatwierdzeniu, np. commit message, or pass it to git stash show:

git fsck --no-reflog | \
awk '/dangling commit/ {print $3}' | \
xargs git log --no-walk --format="%H" \
  --grep="WIP on" --min-parents=3 --max-parents=3 | \
xargs -n1 -I '{}' bash -c "\
  git log -1 --format=medium --color=always '{}'; echo; \
  git stash show --color=always '{}'; echo; echo" | \
less -R
 9
Author: Brad Feehan,
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-05-17 04:33:50

Nie mogłem uzyskać żadnej z odpowiedzi do pracy na Windows w prostym oknie poleceń (Windows 7 w moim przypadku). awk, grep i Select-string nie były rozpoznawane jako komendy. Więc próbowałem innego podejścia:

  • pierwszy bieg: git fsck --unreachable | findstr "commit"
  • skopiuj wyjście do notatnika
  • Znajdź Zastąp "unreachable commit" przez start cmd /k git show

Będzie wyglądać mniej więcej tak:

start cmd /k git show 8506d235f935b92df65d58e7d75e9441220537a4 start cmd /k git show 44078733e1b36962571019126243782421fcd8ae start cmd /k git show ec09069ec893db4ec1901f94eefc8dc606b1dbf1 start cmd /k git show d00aab9198e8b81d052d90720165e48b287c302e

  • Zapisz jako .plik bat i uruchom go
  • skrypt otworzy kilka poleceń windows, pokazujący każdy commit
  • jeśli znalazłeś ten, którego szukasz, Uruchom: git stash apply (your hash)

Może nie jest to najlepsze rozwiązanie, ale zadziałało dla mnie

 8
Author: kromakollision,
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
2017-02-28 15:01:39

To, czego tu Szukałem, to jak odzyskać towar, niezależnie od tego, co sprawdziłem. W szczególności, schowałem coś, potem sprawdziłem starszą wersję, a następnie popchnąłem, ale skrytka była nieaktywna w tym wcześniejszym momencie czasowym, więc skrytka zniknęła; nie mogłem po prostu zrobić {2]}, aby odepchnąć ją z powrotem na stos. To mi się udało:

$ git checkout somethingOld
$ git stash pop
...
nothing added to commit but untracked files present (use "git add" to track)
Dropped refs/stash@{0} (27f6bd8ba3c4a34f134e12fe69bf69c192f71179)
$ git checkout 27f6bd8ba3c
$ git reset HEAD^    # Make the working tree differ from the parent.
$ git stash # Put the stash back in the stack.
Saved working directory and index state WIP on (no branch): c2be516 Some message.
HEAD is now at c2be516 Some message.
$ git checkout somethingOld # Now we are back where we were.

Z perspektywy czasu, powinienem był używać git stash apply, a nie git stash pop. Robiłem bisect i miałem małą łatkę, którą chciałem stosować na każdym kroku bisect. Teraz to robię:

$ git reset --hard; git bisect good; git stash apply
$ # Run tests
$ git reset --hard; git bisect bad; git stash apply
etc.
 4
Author: Ben,
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
2013-11-07 15:13:25

Odzyskano go za pomocą następujących kroków:

  1. Zidentyfikuj usunięty kod hashowy skrytki:

    Gitk --all $ (git fsck --no-reflog / awk ' / dangling commit / {print $3}')

  2. Cherry Wybierz skrytkę:

    Git cherry-pick-m 1 $stash_hash_code

  3. Rozwiązuj konflikty, jeśli występują, używając:

    Git mergetool

DODATKOWO możesz mieć problemy z Komunikatem commit, jeśli używasz gerrit. Proszę Schowaj swoje zmiany przed następnymi alternatywami:

  1. Użyj hard reset do poprzedniego zatwierdzenia, a następnie Przywróć tę zmianę.
  2. Możesz również ukryć zmiany, rebase i ponownie.
 4
Author: Abhijeet,
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-02-16 11:20:14

Możesz wypisać wszystkie nieosiągalne commity, pisząc to polecenie w terminalu -

git fsck --unreachable

Sprawdź unreachable commit hash-

git show hash

Wreszcie Zastosuj, Jeśli znajdziesz ukryty element -

git stash apply hash
 4
Author: Vivek Kumar,
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-03-07 11:31:52

Inny powszechny przypadek użycia: próbowałeś wskoczyć na niewłaściwą gałąź i masz konflikty?

Wszystko, co chcesz, to cofnąć pop, ale nadal trzymać go na liście schowka, dzięki czemu można go wyskakiwać na właściwej gałęzi.

Aby to naprawić, wykonaj następujące czynności:

git reset HEAD --hard
git checkout my_correct_branch
git stash pop
Zrobione!
 0
Author: dorony,
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-02-07 11:41:52

Przypadkowo usunąłem skrytkę w aplikacji GitUP. Wystarczy nacisnąć Ctrl + Z, aby go cofnąć.

Może to komuś pomoże;)

 0
Author: Nik Kov,
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-27 09:52:37