DEV Community

Vlad-Raul Guran
Vlad-Raul Guran

Posted on Originally published at vladguran.github.io

Git Advanced Workflows & Recovery Cheat Sheet

Rewrite history safely, run parallel workflows, and recover almost any lost work. Targets Git 2.45+; every feature used here has been available since Git 2.38 or earlier.

Quick Reference

Task Command
Show every HEAD move git reflog
Undo last reset/rebase/merge git reset --hard ORIG_HEAD
Restore a file from any commit git restore --source=<sha> -- path
Unstage, keep edits git restore --staged path
Fold staged changes into an old commit git commit --fixup=<sha> then git rebase -i --autosquash <base>
Move a branch to a new base git rebase --onto <newbase> <oldbase> <branch>
Compare two versions of a series git range-diff <base> <old-tip> <new-tip>
Find the regression commit git bisect start <bad> <good> then git bisect run <cmd>
Work on a second branch in parallel git worktree add ../hotfix -b hotfix origin/main
Safe force-push git push --force-with-lease --force-if-includes
Undo a pushed merge git revert -m 1 <merge-sha>
Copy a commit, recording its origin git cherry-pick -x <sha>
Find when a string appeared or vanished git log -S'needle' --oneline
Show the history of a function git log -L :funcName:path/file.c
Find lost commits and blobs git fsck --lost-found

Core Patterns

1. Reflog: undo almost anything

Every move of HEAD and of each branch tip is logged locally. By default, unreachable entries are kept for 30 days and reachable ones for 90 days. If a command "destroyed" commits, they are almost certainly still in the reflog.

git reflog                               # HEAD history, newest first
git reflog show feature/login            # one branch's tip history
git log -g --oneline --date=relative     # reflog with relative timestamps
git reset --hard HEAD@{1}                # go back to where HEAD was before the last move
git reset --hard ORIG_HEAD               # set by reset, rebase, merge, and am
git branch rescue HEAD@{5}               # recover without touching the current branch
git switch -c rescue 'main@{2.hours.ago}'  # time-based ref syntax
# Deleted branch: `git branch -d` prints "(was abc1234)". Otherwise:
git reflog | grep -A1 'moving from feature/login'  # the 2nd (older) line is the old tip
git branch feature/login <sha>
Enter fullscreen mode Exit fullscreen mode

2. Dangling objects: dropped stashes and lost staged work

A stash is a commit. A file you staged with git add is stored as a blob. Both survive git stash drop or git reset --hard until garbage collection removes them.

# Find a dropped or cleared stash (its subject looks like "WIP on <branch>" or "On <branch>")
git fsck --no-reflog | awk '/dangling commit/ {print $3}' \
  | xargs git log --no-walk --format='%h %cr %s'
git stash apply <sha>
# Find work that was staged but never committed, then lost to reset --hard
git fsck --lost-found                    # writes to .git/lost-found/{commit,other}/
git show <blob-sha> > recovered.txt
# Edits that were never staged were never stored. Git cannot recover them.
Enter fullscreen mode Exit fullscreen mode

This is the free part. The full Git Advanced Workflows & Recovery Cheat Sheet (production commands, best practices, common pitfalls and a debugging checklist on 2–4 dense pages) is available as a PDF, pay what you want: https://guranova.gumroad.com/l/cilot

More sheets: https://vladguran.github.io/dev-cheatsheets/

This article was written with AI assistance.

Top comments (0)