Git Basics: Recovering a Detached Commit with Reflog
A reflog records local updates to references such as HEAD. It can help find a commit you made and then left behind without putting it on a branch.
Run these commands in Bash with Git 2.28 or newer installed. Start a fresh temporary repository for this article:
git_practice=$(mktemp -d) || exit
mkdir "$git_practice/repository"
cd "$git_practice/repository" || exit
git init -q -b main
git config user.name 'Practice User'
git config user.email 'practice@example.invalid'
git config commit.gpgsign falseThe identity and signing settings apply only to this repository. Use your own identity in real projects. The temporary files remain afterward. Examples assume default Git settings; if a pager opens, press q to leave it.
Make a detached commit
printf 'port=8080
' > app.conf
git add app.conf
git commit -q -m 'Add application config'
git switch -q --detach
printf 'port=9090
' > app.conf
git add app.conf
git commit -q -m 'Try another port'
git log -1 --format=%sTry another portDetached HEAD means you are working directly from a commit rather than a branch. The new commit exists, but no branch name points to it.
Find it after switching away
git switch -q main
cat app.conf
git reflog -2 --format='%gs'port=8080
checkout: moving from <commit-id> to main
commit: Try another port<commit-id> stands for your actual commit ID. Git may also print a warning about leaving a commit behind, including its variable ID. The reflog shows the recent HEAD moves. Immediately after this switch, HEAD@{1} identifies the commit we just left. That position changes when more HEAD updates happen; inspect your own reflog before using a selector in real work.
Give the commit a branch
git branch recovered-port 'HEAD@{1}'
git show recovered-port:app.conf
git log -1 --format=%s recovered-port
git branch --show-currentport=9090
Try another port
mainThe new branch keeps the commit reachable. Creating it does not change your working files or switch away from main. You can inspect the recovered work before merging or cherry-picking it.
Know the limits
Reflogs are local; they are not shared by pushing or cloning. Entries expire, and unreachable objects can eventually be removed by garbage collection. Recovery is not guaranteed after that. Reflog also cannot restore ordinary uncommitted edits that Git never recorded. Keep backups and commit useful work rather than treating reflog as a backup system.
References
git-reflog manual, git-branch manual
Acknowledgements
This post was created with assistance from AI.