Learn / Programming / Git & Command Line / Undoing Things and Team Workflows

Git & Command Line · Lesson 5 of 5

Undoing Things and Team Workflows

Restore, reset, revert, stash and the reflog safety net.

  • Advanced
  • 15 min read
  • 3 objectives

Before this lessonLesson 4: Remotes, GitHub and Pull Requests

What you will learn

  • Undo safely
  • Use stash
  • Recover with reflog

Everyone makes mistakes: a commit in the wrong branch, a bad edit, a message typo. Git gives you many ways to undo, but they behave differently. Knowing which is safe on shared history versus local history keeps you out of trouble.

Mistakes are cheap in Git

The reason experienced developers are relaxed about Git is that almost everything can be undone, as long as it was committed. The trick is choosing the right undo for the situation. Ask two questions: Has it been committed? and Has it been pushed and shared? The answers pick the tool.

  • Not committed yet → git restore (throws away edits).
  • Committed, not pushed → git commit --amend or git reset (rewrites your own history).
  • Already pushed and shared → git revert (adds a new commit that cancels the old one; never rewrites shared history).

Discard uncommitted changes

git restore file.txt              # throw away edits to a file (cannot be undone!)
git restore --staged file.txt     # unstage, keep the edits
git clean -n                      # preview untracked files that would be removed

Fix the last commit

git commit --amend -m "Better message"   # change message
git add forgotten.txt
git commit --amend --no-edit               # add a file to the last commit

--amend rewrites the last commit, so only do it before you push.

revert: the safe undo for shared history

git revert creates a new commit that reverses an earlier one. History is preserved, so it is safe to push.

git revert a1b2c3d

reset: move the branch pointer

git reset --soft HEAD~1    # undo the commit, keep changes staged
git reset HEAD~1           # undo the commit, keep changes unstaged (--mixed)
git reset --hard HEAD~1    # undo the commit AND delete the changes

stash: set work aside

Need to switch branches but your changes are not ready to commit?

git stash push -m "wip login form"
git switch other-branch
# ...do something...
git switch -
git stash list
git stash pop            # bring the changes back

reflog: your safety net

Git records every place HEAD has been, for about 90 days, even for commits no branch points to. If you think you lost work after a bad reset or a deleted branch, look here.

git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# 9f8e7d6 HEAD@{1}: commit: Add checkout page
git reset --hard 9f8e7d6      # jump back to before the mistake

Other useful tools

  • git cherry-pick <sha>: copy one commit onto the current branch.
  • git bisect: binary search through history to find the commit that introduced a bug.
  • git tag v1.0.0: mark a release.

Team workflow summary

  • GitHub Flow: short-lived branches and PRs into main, deploy from main. Simple and popular.
  • Trunk-based: very small changes merged to main daily, behind feature flags.
  • Git Flow: long-lived develop and release branches. Heavier; suited to versioned releases.

Situation 1: I edited a file and want the old version back

$ git status
  modified:   index.html
$ git restore index.html          # discards the edits (cannot be undone!)
$ git status
nothing to commit, working tree clean

Situation 2: I committed too early or with a typo in the message

$ git commit -m "Add serch box"
$ git commit --amend -m "Add search box"   # fixes the last commit message

$ git add forgotten-file.css
$ git commit --amend --no-edit               # adds the file to the last commit

Situation 3: a bad commit is already on GitHub

$ git log --oneline
9d1e4b7 Break the login page
3f2a91c Create homepage

$ git revert 9d1e4b7        # creates a new commit that undoes it
[main c07be21] Revert "Break the login page"

Because revert only adds history, teammates who already pulled the bad commit are not affected, and the story stays honest.

Situation 4: I need to switch tasks but my work is half done

$ git stash                 # sets your edits aside, working tree is clean
$ git switch hotfix         # fix something urgent...
$ git switch main
$ git stash pop             # bring your unfinished work back

Situation 5: "I lost a commit!"

Git keeps a private diary of everywhere your branch has pointed, called the reflog. Even after a bad reset the commit is usually still there for weeks.

$ git reflog
c07be21 HEAD@{0}: revert: Revert "Break the login page"
9d1e4b7 HEAD@{1}: commit: Break the login page
3f2a91c HEAD@{2}: commit (initial): Create homepage

$ git reset --hard 3f2a91c   # jump back to any of those points

Key takeaways

  • Pick the undo by asking: committed? pushed?
  • restore for edits, amend/reset for local commits, revert for shared ones.
  • stash parks unfinished work; reflog finds "lost" commits.
  • Never rewrite history that others have already pulled.
# Write your solution here
Course completeYou finished Git & Command LineReview the full course or pick your next one.