100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Bash

git reset Explained

How git reset moves the current branch pointer and optionally rewrites the staging area and working directory, and the meaningful difference between its --soft, --mixed, and --hard modes.

Undoing ChangesIntermediate9 min readJul 9, 2026
Analogies

git reset Explained

git reset is one of the most powerful and most misunderstood commands in Git because it does two conceptually separate things depending on how it's invoked: it moves where the current branch pointer (HEAD) points to, and — depending on the mode — it can also rewrite the staging area (the index) and the working directory to match. Used carefully, reset is how you unstage files, undo local commits, or throw away uncommitted changes entirely. Used carelessly, particularly with --hard, it is how people lose work, because --hard overwrites the working directory with no confirmation and no automatic backup.

🏏

Cricket analogy: Like a scorer who can move the innings marker back to an earlier over while keeping every run already noted (careful use), but hitting the "wipe the entire scoresheet" option instantly erases all runs scored since with no undo and no backup copy saved anywhere.

The three modes

git reset --soft <commit> moves HEAD (and the current branch) to the given commit but leaves the staging area and working directory untouched — everything that was in commits after that point becomes staged, uncommitted changes. git reset --mixed <commit> (the default if no flag is given) also moves HEAD, but additionally resets the staging area to match the target commit, so those changes become unstaged-but-present in the working directory. git reset --hard <commit> goes further still: it moves HEAD and resets both the staging area and the working directory to exactly match the target commit, discarding any uncommitted changes and any commits after the target point from the branch.

🏏

Cricket analogy: Like reverting the official scorecard to an earlier over but keeping every run scored since as "unofficial, pending confirmation" (soft), versus also clearing the confirmation stamps so those runs sit unconfirmed on the field (mixed), versus wiping both the scorecard and the field record entirely back to that earlier over (hard).

bash
# Undo the last commit but keep its changes staged, ready to re-commit
git reset --soft HEAD~1

# Undo the last commit and unstage its changes, but keep them in the
# working directory (files still show the edits, just not staged)
git reset --mixed HEAD~1   # --mixed is the default; `git reset HEAD~1` is equivalent

# Discard the last commit AND all its changes completely
git reset --hard HEAD~1

# Unstage a single file without touching the working directory or moving HEAD
git reset HEAD -- src/config/settings.py

# Move a branch to point at a specific commit found via `git log`
git reset --hard 4f2a9c1

Reset versus checkout versus restore

Because reset touches HEAD, the index, and the working directory in different combinations depending on its mode, modern Git split some of its jobs out into more explicit commands: git restore now handles restoring working-directory files or unstaging index entries without moving the branch pointer at all, and git switch handles changing branches. git reset remains the command for actually moving the branch pointer — undoing commits at the branch level — which restore and switch deliberately do not do.

🏏

Cricket analogy: Like a board splitting the old all-purpose team-manager role into a dedicated fitness restorer who only handles player conditioning (restore) and a dedicated squad-rotation officer who only handles swapping the playing group (switch), while the team-manager role itself narrows to just deciding which match result counts as official (reset moving the branch pointer).

A useful mental model: --soft only moves the label (HEAD/branch); --mixed also erases the staging area's memory of the difference; --hard also overwrites the actual files on disk. Each flag reaches one layer further into the three trees Git tracks — commit, index, working directory.

git reset --hard permanently discards uncommitted changes in the working directory with no prompt — there is no undo for changes that were never committed. Before running it, double-check with git status and git diff, or stash first with git stash if there's any chance you'll want the changes back.

  • git reset moves the current branch's HEAD pointer to a given commit.
  • --soft leaves the index and working directory untouched — prior changes become staged.
  • --mixed (the default) also resets the index — prior changes become unstaged but present in the working directory.
  • --hard also overwrites the working directory, discarding uncommitted changes permanently.
  • git restore and git switch now cover some jobs reset used to do, leaving reset focused on moving the branch pointer.
  • Reset rewrites history on the current branch — avoid it on commits already pushed and shared with others.

Practice what you learned

Was this page helpful?

Topics covered

#Bash#GitVersionControlStudyNotes#SoftwareEngineering#GitResetExplained#Git#Reset#Explained#Three#StudyNotes#SkillVeris