Git/
Lesson

You made commits you regret. Maybe the commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed. message was wrong. Maybe you included files you should not have. Maybe you want to split one big commit into several smaller ones. Git reset is the time machine that lets you undo commits, but it comes in three modes with very different consequences.

Understanding the difference between soft, mixed, and hard reset is critical because one of them destroys data permanently while the other two are completely safe.

AI assistants like ChatGPT and Copilot frequently suggest git reset --hard as the first solution for almost any undo scenario. They treat it as a quick fix, but --hard permanently deletes uncommitted work. In most cases, --soft or --mixed does what you actually need without any data loss.

The three modes of git reset

Think of the three modes as levels of intensity:

ModeHEAD movesStaging areaWorking directoryData loss
--softYesUnchanged (staged)UnchangedNo
--mixedYesReset (unstaged)UnchangedNo
--hardYesResetReset to match HEADYes, permanent

Soft reset: undo commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed., keep changes staged

git reset --soft HEAD~1

This moves HEADWhat is head?A special pointer in Git that indicates the commit you are currently working on - usually the tip of the active branch. back one commit but leaves all changes from that commit in the staging areaWhat is staging area?A holding zone in Git where you place changes you want to include in your next commit, letting you select exactly which modifications to save., ready to be recommitted. Nothing is lost.

Use case: fix a commit message or add a forgotten file

# You committed but forgot to add the tests
git reset --soft HEAD~1

# All changes are still staged
git add auth.test.js

# Commit everything together with a better message
git commit -m "feat: add user authentication with tests"

Mixed reset: undo commit, unstage changes

git reset HEAD~1
# or explicitly
git reset --mixed HEAD~1

This moves HEAD back and unstages the changes, but keeps them in your working directory. Nothing is lost.

Use case: split a big commit into smaller ones

# You made one messy commit with everything
git reset HEAD~1

# Changes are now unstaged - stage and commit selectively
git add auth.js
git commit -m "feat: implement JWT authentication"

git add styles.css
git commit -m "style: update login form styling"

git add README.md
git commit -m "docs: add authentication setup instructions"

Hard reset: undo commit and destroy all changes

git reset --hard HEAD~1

This is the nuclear option. It moves HEAD back, clears the staging area, and resets your working directory to match. All changes are permanently deleted.

git reset --hard is irreversible. Once you run it, changes are gone from your working directory, staging area, and commit history. The only recovery path is if you find the old commit hash in git reflog before garbage collection runs. Never use --hard unless you are 100% certain you do not need those changes.

The only safe use cases for --hard:

  • You truly want to discard an experiment and start fresh
  • You committed sensitive data (passwords, APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. keys) and want it gone
  • You are absolutely certain you do not need the changes

02

Understanding HEADWhat is head?A special pointer in Git that indicates the commit you are currently working on - usually the tip of the active branch. references

ReferenceMeaning
HEADCurrent commit
HEAD~1 or HEAD^One commit before HEAD
HEAD~2Two commits before HEAD
HEAD~3Three commits before HEAD
abc1234Specific commit by hash
# Go back 1 commit
git reset --soft HEAD~1

# Go back 3 commits
git reset --mixed HEAD~3

# Go to a specific commit
git reset --hard abc1234
03

The golden rule: never reset shared history

Git reset rewrites history. This is fine for local, unpushed commits. It is catastrophic for shared, pushed commits.

# DANGEROUS: resets pushed commits
git reset --hard HEAD~3
git push --force    # Destroys work others depend on

If other people have pulled those commits and built on them, your force pushWhat is force push?A destructive Git push that overwrites the remote branch history with your local version, which can break teammates' work if they already pulled the original. creates chaos. For anything that has been pushed, use git revert instead, which creates new commits that undo changes without rewriting history.

04

Unstaging files with reset

A common use of git reset that has nothing to do with commits:

# You accidentally staged a sensitive file
git add config.env    # Oops

# Unstage it (keep the modifications)
git reset HEAD config.env

# Modern alternative (clearer intent)
git restore --staged config.env

This does not move HEADWhat is head?A special pointer in Git that indicates the commit you are currently working on - usually the tip of the active branch. or affect commits. It just removes files from the staging areaWhat is staging area?A holding zone in Git where you place changes you want to include in your next commit, letting you select exactly which modifications to save..

05

Quick reference

Use caseCommand
Fix commit messagegit reset --soft HEAD~1 then git commit
Add forgotten file to last commitgit reset --soft HEAD~1, git add file, git commit
Split a commit into smaller onesgit reset HEAD~1 then selective git add and git commit
Combine multiple commitsgit reset --soft HEAD~n then git commit
Unstage a filegit reset HEAD file or git restore --staged file
Discard everything (dangerous)git reset --hard HEAD~1