Written on November 19, 2025
A script to find lost Git commits, stashes, or other changes
This script helped me find lost stashes that contained a lot of important changes, so I wanted to share it here for others who might find themselves in a similar situation.
Important: Git's garbage collection eventually deletes unreachable commits (typically after 30 days), so run this script as soon as you realize something is missing.
#!/bin/bash
#
# git-find-lost-code.sh
# A script to find lost Git commits, stashes, or other changes.
#
# This script searches for "lost" commits in two places:
# 1. Unreachable commits: Commits that are no longer referenced by any branch,
# tag, or stash. This is where dropped stashes and hard-resets end up.
# 2. The Reflog: A log of all recent movements of HEAD, which acts as a
# powerful safety net.
#
# USAGE:
# chmod +x git-find-lost-code.sh
# ./git-find-lost-code.sh [optional/path/to/file]
#
# If you provide a file path, the script will only show commits that modified
# that specific file. If you don't, it will show ALL lost commits it can find.
# Note: Without a file path, the reflog search may output many commits.
set -e
FILE_PATH="$1"
# --- Method 1: Search Dangling (Unreachable) Commits ---
echo "---"
echo "🔎 Searching for dangling (unreachable) commits..."
echo "---"
UNREACHABLE_COMMITS=$(git fsck --unreachable | grep commit | cut -d' ' -f3)
if [ -z "$UNREACHABLE_COMMITS" ]; then
echo "No dangling commits found."
else
FOUND_IN_FSCK=0
for commit in $UNREACHABLE_COMMITS; do
if [ -n "$FILE_PATH" ]; then
# If a file path is provided, check if the commit modified it
if git show --name-only --pretty="" "$commit" 2>/dev/null | grep -q "^${FILE_PATH}$"; then
echo "✅ Found dangling commit [$commit] that modified '$FILE_PATH':"
git log -n 1 --oneline --stat "$commit"
echo "------------------------------------------------"
FOUND_IN_FSCK=1
fi
else
# If no file path, just show all dangling commits
echo "✅ Found dangling commit [$commit]:"
git log -n 1 --oneline --stat "$commit"
echo "------------------------------------------------"
FOUND_IN_FSCK=1
fi
done
if [ "$FOUND_IN_FSCK" -eq 0 ]; then
echo "No dangling commits found that modified '$FILE_PATH'."
fi
fi
# --- Method 2: Search The Reflog ---
echo ""
echo "---"
echo "🔎 Searching reflog..."
echo "---"
REFLOG_COMMITS=$(git reflog | awk '{print $1}')
FOUND_IN_REFLOG=0
for commit in $REFLOG_COMMITS; do
if [ -n "$FILE_PATH" ]; then
# If a file path is provided, check if the commit modified it
if git show --name-only --pretty="" "$commit" 2>/dev/null | grep -q "^${FILE_PATH}$"; then
echo "✅ Found reflog commit [$commit] that modified '$FILE_PATH':"
git log -n 1 --oneline --stat "$commit"
echo "------------------------------------------------"
FOUND_IN_REFLOG=1
fi
else
# If no file path, just show all reflog commits
echo "✅ Found reflog commit [$commit]:"
git log -n 1 --oneline --stat "$commit"
echo "------------------------------------------------"
FOUND_IN_REFLOG=1
fi
done
if [ "$FOUND_IN_REFLOG" -eq 0 ]; then
echo "No commits found in reflog that modified '$FILE_PATH'."
fi
echo ""
echo "✨ Search complete."
echo ""
echo "💡 To recover a commit you found:"
echo " - Cherry-pick it: git cherry-pick <commit-hash>"
echo " - Create a branch: git checkout -b recovery-branch <commit-hash>"
echo " - View the changes: git show <commit-hash>"
git-find-lost-code.sh)chmod +x git-find-lost-code.sh./git-find-lost-code.sh./git-find-lost-code.sh path/to/file.txtOnce you've found the commit you're looking for, you can recover it using:
git cherry-pick <commit-hash>git checkout -b recovery-branch <commit-hash>git show <commit-hash>git show <commit-hash> | git apply