I lost a commit
A commit you made is almost never gone. Every move of HEAD is written to the reflog, and a commit
stays in the repository for weeks after nothing points at it. Three ways to lose one, and the way back from
each.
A reset went too far
$ git reset --hard HEAD~1 HEAD is now at ab5768d api: the first endpoint $ git log --oneline ab5768d api: the first endpoint 07dec17 readme: the project $ git reflog ab5768d HEAD@{0}: reset: moving to HEAD~1 5a5bc93 HEAD@{1}: commit: auth: check the token ab5768d HEAD@{2}: commit: api: the first endpoint 07dec17 HEAD@{3}: commit (initial): readme: the project $ git reset --hard HEAD@{1} HEAD is now at 5a5bc93 auth: check the token $ git log --oneline 5a5bc93 auth: check the token ab5768d api: the first endpoint 07dec17 readme: the project
git reflog lists where HEAD has been, newest first: the reset at
HEAD@{0}, the commit it took away at HEAD@{1}.
git reset --hard HEAD@{1}
moves the branch back there. Some shells want the braces quoted.
A branch was deleted
$ git branch -D feature Deleted branch feature (was 5a5bc93). $ git reflog ab5768d HEAD@{0}: checkout: moving from feature to main 5a5bc93 HEAD@{1}: commit: auth: check the token ab5768d HEAD@{2}: checkout: moving from main to feature ab5768d HEAD@{3}: commit: api: the first endpoint 07dec17 HEAD@{4}: commit (initial): readme: the project $ git branch feature HEAD@{1} $ git log --oneline feature 5a5bc93 auth: check the token ab5768d api: the first endpoint 07dec17 readme: the project
git branch -D prints the hash it deleted, which is one way back:
git branch feature and that hash. The reflog is the other: the commit sits at
HEAD@{1}, under the checkout that left the branch, and git branch feature HEAD@{1}
makes the branch again, pointing at it.
A rebase dropped it
$ git log --oneline 7a20dd4 api: add the endpoint ab5768d api: the first endpoint 07dec17 readme: the project $ git reflog 7a20dd4 HEAD@{0}: pull --rebase -X ours (finish): returning to refs/heads/main 7a20dd4 HEAD@{1}: pull --rebase -X ours (start): checkout 7a20dd4815012ed0c8bcd4fad2eae46182e82c61 a97e6d9 HEAD@{2}: commit: api: rename the endpoint ab5768d HEAD@{3}: commit: api: the first endpoint 07dec17 HEAD@{4}: commit (initial): readme: the project $ git reset --hard ORIG_HEAD HEAD is now at a97e6d9 api: rename the endpoint $ git log --oneline a97e6d9 api: rename the endpoint ab5768d api: the first endpoint 07dec17 readme: the project
A rebase that settles every clash in the other side's favour (the conflict page's
-X ours) can leave your commit with nothing to apply, and drop it. The reflog shows the rebase's
start and finish, and Git keeps the branch's tip from before any rebase, merge or reset in
ORIG_HEAD, so git reset --hard ORIG_HEAD is the whole undo. A
pull after a forced push can drop a commit the same way.
Undo the last commit, keep the work
$ git reset --soft HEAD~1 $ git status --short A auth.js
The most asked Git question has the smallest answer. --soft moves the branch back one commit and
leaves everything that commit had, staged and ready to commit again. --hard throws the changes
away as well, which is the first case above.
What the reflog can't bring back
The reflog is per clone: it records your HEAD, not the remote's, so it has nothing on a commit
that only ever existed on someone else's machine. It holds commits, not uncommitted work: changes that were
never committed are gone after git reset --hard. And its entries expire, after 90 days, or 30 for
a commit nothing reaches any more.
Why the game does this to you
In Git Game nothing is lost either: every pack ever sent is in the game's log, and any game can be replayed day
by day from it. On the table, the reflog card is the one you play after a
push --force erased your commits: armed in your pack, it fires inside the forcer's pack and puts
them back on top of main.
Play a day where this happens
One tap starts a game against the bot, and every day of it can be replayed afterwards.
Output captured from Git 2.50.1 (Apple Git-155) by scripts/git-output.sh, in a scratch repository with two clones, ana's and bot's, and fixed dates, so the hashes are the same on every run. It is captured again at every Git release.