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!
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.
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ć.
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.
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
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.
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.
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
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
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
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.
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.
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.
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
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
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.
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:
-
Zidentyfikuj usunięty kod hashowy skrytki:
Gitk --all $ (git fsck --no-reflog / awk ' / dangling commit / {print $3}')
-
Cherry Wybierz skrytkę:
Git cherry-pick-m 1 $stash_hash_code
-
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:
- Użyj hard reset do poprzedniego zatwierdzenia, a następnie Przywróć tę zmianę.
- Możesz również ukryć zmiany, rebase i ponownie.
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
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!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;)
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