
The git reset
command lets you undo commits, unstage files, or discard changes from your working directory. It works by modifying Git's three main states, HEAD, Index, and Working Directory, depending on the option used. While powerful, git reset
can be destructive if used carelessly, especially with --hard
. This article explains how it works and when to use each option.
Git Reset Common Options
Git offers three main options for the reset
command. Each affects the repository’s HEAD, staging area (Index), and working directory differently. The table below summarizes their behavior:
Flag | HEAD | Staging Area | Working Dir | Summary |
---|---|---|---|---|
--soft |
Yes | No | No | Keeps changes staged |
--mixed |
Yes | Yes | No | Unstages but keeps file changes |
--hard |
Yes | Yes | Yes | Discards all committed changes |
Let’s explore how each option works in practice with syntax, behavior, and typical use cases.
git reset --soft
Command Syntax and Breakdown
git reset --soft <commit>
git reset
: Base command that modifies Git history.--soft
: Moves theHEAD
pointer but leaves the staging area and working directory unchanged.<commit>
: The target commit to reset to (e.g.,HEAD~1
, a specific commit hash).
What the Flag Does
- Moves
HEAD
to the specified commit. - Leaves all changes from the reset commit staged (in the index).
- Does not touch your working directory or file contents.
Use this when you want to amend or rework the previous commit without redoing the changes manually.
Command Demonstration
Assume you made a second commit but realized you want to reword it or combine it with the first.
console$ git log --oneline
Output:
abc1234 Second commit def5678 Initial commit
Reset the last commit but keep its changes staged.
console$ git reset --soft HEAD~1
This command removes
abc1234
from history, but the changes remain staged.Check the current Git state.
console$ git status
Output:
On branch main Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: file.txt
Recreate or amend the commit.
console$ git commit -m "Amended commit"
This creates a new commit with the same changes, allowing you to update the message or combine changes.
git reset --mixed
(default)
Command Syntax
git reset --mixed <commit>
git reset
: Base command that modifies Git history.--mixed
: Resets theHEAD
and updates the staging area to match the target commit. It leaves your working directory unchanged.<commit>
: The commit hash or reference to reset to (e.g.,HEAD~1
).
If no flag is provided, Git defaults to --mixed
.
What the Flag Does
- Moves
HEAD
to the specified commit. - Clears the staging area (Index) to match the target commit.
- Keeps all changes in your working directory.
Use this when you want to undo a commit and unstage its changes, but continue editing your files.
Command Demonstration
View your recent commits.
console$ git log --oneline
Output:
abc1234 Second commit def5678 Initial commit
Reset the last commit and unstage the changes.
console$ git reset --mixed HEAD~1
This removes the most recent commit (
abc1234
) from history and clears the staging area, while keeping the changes in your working directory.Check the current Git state.
console$ git status
Output:
On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) modified: file.txt
Restage and recommit if needed.
console$ git add file.txt
console$ git commit -m "Revised commit"
This approach is helpful when you want to revise or split changes without losing your progress.
git reset --hard
Command Syntax
git reset --hard <commit>
git reset
: Base command that modifies Git history.--hard
: ResetsHEAD
, the staging area, and the working directory to match the target commit.<commit>
: The commit hash or reference to reset to (e.g.,HEAD~1
).
Use --hard
with caution, as it permanently deletes committed changes unless recoverable via git reflog
.
What the Flag Does
- Moves
HEAD
to the specified commit. - Clears the staging area to match that commit.
- Replaces the contents of your working directory with the version from that commit.
Use this when you want to completely discard changes and revert your repository to a clean state.
Command Demonstration
View your commit history.
console$ git log --oneline
Output:
abc1234 Buggy commit def5678 Stable baseline
Perform a hard reset to discard recent changes.
console$ git reset --hard HEAD~1
This resets
HEAD
, clears the staging area, and restores all files to the state of the previous commit (def5678
).Confirm the reset state.
console$ git status
Output:
On branch main nothing to commit, working tree clean
All file modifications from the discarded commit are gone. If you need to recover them, use
git reflog
.
Reset Changes in Git
You can use git reset
to move your project back to a specific commit in history. This section explains the syntax, flag behavior, and demonstrates how to reset changes safely and intentionally. These commands are ideal for safely navigating through commit history during iterative development.
Command Syntax
git reset [--soft|--mixed|--hard] <commit>
--soft
: MovesHEAD
to the target commit and keeps changes staged.--mixed
: MovesHEAD
and unstages changes while preserving working directory content.--hard
: ResetsHEAD
, Index, and working directory — discards all changes.<commit>
: Target commit hash or relative reference (e.g.,HEAD~2
,a1b2c3d
).
If no flag is provided, Git defaults to --mixed
.
Reset to a Specific Commit
List your commit history to find the target hash.
console$ git log --oneline
Output:
a1b2c3d Fix typo 9f8e7d6 Add login feature 8e7f6a5 Initial commit
Reset to a specific commit using
--soft
,--mixed
, or--hard
.Soft Reset (keep changes staged)
console$ git reset --soft a1b2c3d
Use this to reword or group commits without modifying your working directory.
Mixed Reset (default, keep file changes but unstage them).
console$ git reset --mixed a1b2c3d
Use this when you want to review or edit file changes after rollback.
Hard Reset (discard all changes).
console$ git reset --hard a1b2c3d
This removes all local changes and resets your project to the specified commit.
Use
git reflog
if you need to recover after an accidental reset.
Undo Reset Changes in Git
You can undo a git reset
by using the reflog
, which tracks the movement of HEAD
and other references.
Command Syntax and Breakdown
git reflog
- Shows recent changes to
HEAD
, including resets and commits.
$ git reset --hard HEAD@{n}
- Resets to a previous state from the reflog.
HEAD@{n}
refers to how many actions ago that state was (e.g.,HEAD@{1}
is one step back).
Command Demonstration
Perform a reset.
console$ git reset --hard HEAD~1
View the reflog.
console$ git reflog
Output:
abc1234 HEAD@{0}: reset: moving to HEAD~1 def5678 HEAD@{1}: commit: Add login feature
Undo the reset.
console$ git reset --hard HEAD@{1}
This restores the previous commit and discards the effects of the reset.
git reflog
works with all reset types (--soft
, --mixed
, --hard
). However, it’s most critical for --hard
, which removes changes from the working directory and index. Make sure you act before git gc
prunes unreachable commits.
Conclusion
By learning how to use git reset
, you now understand how to undo commits, unstage changes, and discard unwanted modifications from your Git history. This command gives you precise control over the HEAD, staging area, and working directory, making it a crucial tool in any developer’s workflow.
Use the appropriate reset type based on what you want to preserve:
- Use
--soft
to undo commits while keeping changes staged. - Use
--mixed
to unstage changes without touching your working directory. - Use
--hard
to completely discard changes and reset everything, only when you're sure no committed changes need to be kept.