EMZETT.
Login

git stash, reflog and reset: Saving and rescuing changes

In short: With stash you put unfinished work aside, with reset you roll back states, and the reflog helps recover almost any seemingly lost commit.

In more detail: Git stores much more than you think: even after reset --hard, an accidentally deleted branch or a failed rebase you can often rescue everything, as long as you act quickly. A small repertoire suffices.

In Depth

git stash: putting work aside

git stash                    # put current changes aside
git stash -u                 # also new (untracked) files
git stash list               # list
git stash pop                # bring back last stash (and delete)
git stash apply stash@{1}    # bring back a specific one (keep)
git stash drop               # delete
git stash push -m "experiment" file.txt

Useful when you must switch branches quickly without committing. Stashes belong only locally to you; better commit important work into its own branch.

git reset: resetting

  • git reset --soft HEAD~1: undo the last commit, changes stay staged.
  • git reset HEAD~1 (mixed): undo commit, changes stay in the working directory.
  • git reset --hard HEAD~1: discard commit and changes (dangerous!).
  • git restore file discards changes of a file, git restore --staged file removes it from the staging area.
  • On shared branches better git revert <commit> than reset: creates a new commit that undoes the change without rewriting history.

git reflog: the safety net

The reflog records where HEAD and branches pointed in the last weeks:

git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# e4f5g6h HEAD@{1}: commit: New feature
git reset --hard e4f5g6h          # restore old state
git branch rescued e4f5g6h        # or save as a new branch

This recovers lost commits after a wrong reset, rebase or deleted branch (by default about 90 days, only in the local repository).

Typical rescues

  • Branch deleted by accident: git reflog, then git branch name <sha>.
  • Rebase broken: git rebase --abort or git reset --hard ORIG_HEAD.
  • Committed on the wrong branch: git branch new, then on the old one git reset --hard HEAD~1.
  • File deleted but committed: git restore --source=<commit> -- file.
  • Never committed: then Git often cannot help; commit regularly, even unfinished (WIP commits), and tidy up later.

See also: Git, git rebase, git bisect and cherry-pick, Resolving a merge conflict, Push rejected