Day 14/30 - Git Reset: Soft, Hard, and Mixed - Undo Commits at Different Levels
Ruqaiya Beguwala

Ruqaiya Beguwala @ruqaiya_beguwala

About: 👨‍💻 | Software Developer | Open-Source Enthusiast | JavaScript & NodeJS | Think and write about code every single minute

Location:
India
Joined:
Apr 26, 2025

Day 14/30 - Git Reset: Soft, Hard, and Mixed - Undo Commits at Different Levels

Publish Date: Jun 4
1 0

Introduction

Git is a powerful version control system that helps developers track changes in their code. Sometimes, you may commit changes accidentally or realize that you need to undo them. That's where git reset comes in.

The git reset command allows you to undo commits at different levels:

  • --soft - Keeps changes in the staging area.

  • --mixed (default) - Unstages changes but keeps them in the working directory.

  • --hard - Discards all changes completely.

In this guide, we'll explore each option with examples, use cases, and tips to help you undo commits effectively.


1. git reset --soft - Keep Changes Staged

This option moves the HEAD pointer to a previous commit but keeps all changes in the staging area(index).

Example:

git reset --soft HEAD~1
Enter fullscreen mode Exit fullscreen mode

This undoes the last commit but keeps the changes staged.

Use Cases:

  • Fixing commit messages: If you made a typo in the commit message, undo and recommit.

  • Combining commits: Soft reset before amending multiple commits into one.


2. git reset --mixed - Unstage Changes (Default)

This is the default behavior of git reset. It moves the HEAD pointer and unstages changes, but keeps them in the working directory.

Example:

git reset --mixed HEAD~1
# or simply
git reset HEAD~1
Enter fullscreen mode Exit fullscreen mode

This undoes the last commit and unstages changes, but you can still modify and recommit them.

Use Cases:

  • Unstaging files: If you accidentally staged files, reset them.

  • Partial commits: Undo a commit to split it into smaller commits.


3. git reset --hard - Discard All Changes

This is the most dangerous option. It moves the HEAD pointer and deletes all changes in both the staging area and working directory.

Example:

git reset --hard HEAD~1
Enter fullscreen mode Exit fullscreen mode

This completely removes the last commit and all changes.

Use Cases:

  • Complete undo: When you want to discard recent changes entirely.

  • Clean working directory: Reset to a known good state.


Tips & Tricks

Git’s reset is more powerful than most developers realize. Beyond the basic --soft, --mixed, and --hard, below are some hidden behaviors and advanced use cases that can supercharge your Git workflow.

1. Reset a Single File from Another Commit

Most people know git reset works on commits, but you can reset a single file to its state in any commit---without altering the rest of your working directory.

Example:

git reset <commit-hash> -- path/to/file.txt
Enter fullscreen mode Exit fullscreen mode

This unstages file.txt (or resets it to the specified commit) while keeping other changes intact.


2. Interactive Reset (Using --patch)

Want to selectively undo parts of a file? You can use git reset -p (or --patch) to interactively choose which changes to unstage.

Example:

git reset -p
Enter fullscreen mode Exit fullscreen mode

Git will show you each change and ask:

Discard this hunk from index [y,n,q,a,d,?]?

  • y = unstage this change

  • n = keep it staged

  • q = quit


3. Reset While Keeping Untracked Files (--keep)

git reset --hard deletes everything, including untracked files. But --keep is a safer alternative---it resets tracked files but preserves untracked ones.

Example:

git reset --keep HEAD~1
Enter fullscreen mode Exit fullscreen mode

This undoes the last commit but does not delete new files you haven't yet committed.


4. Reset to Re-Apply a Commit Later (--soft + ORIG_HEAD)

When you reset --soft, Git stores the original HEAD in ORIG_HEAD. You can use this to reapply the undone commit later.

Example:

git reset --soft HEAD~1  # Undo last commit (changes stay staged)
# ... make fixes ...
git commit -c ORIG_HEAD  # Reuse the old commit message
Enter fullscreen mode Exit fullscreen mode

5. Partial Reset Using git read-tree (Advanced)

For ultra-precise control, you can use git read-tree with reset to load a specific tree into the index without moving HEAD.

Example:

git read-tree -m -u <commit-hash>
Enter fullscreen mode Exit fullscreen mode

This resets the staging area to match the given commit without changing the working directory.


Bonus: The Secret "Double Reset" Trick

If you reset --hard and regret it, Git keeps your changes for a few seconds in memory. Quickly run:

git reset HEAD@{1}
Enter fullscreen mode Exit fullscreen mode

This undoes the reset if done immediately.

⚠️ Warning: This only works if you haven't run other Git commands yet!


Pro tips

✅ Always check git log before resetting to confirm which commit you’re resetting to.
✅ Use git reflog if you accidentally reset too far—it helps recover lost commits.
✅ Prefer --soft or --mixed unless you’re sure you want to discard changes (--hard).
✅ Test resets in a branch first before applying them to main or master.


Conclusion

Understanding git reset --soft, --mixed, and --hard helps you undo commits safely and efficiently:

--soft → Keeps changes staged.
--mixed → Unstages changes but keeps them in files.
--hard → Deletes everything (use with caution!).

By mastering these commands, you can fix mistakes, reorganize commits, and maintain a clean Git history.


Up Next in the Series: git commit --amend – Modify the last commit


Daily advance GIT tips in your inbox—worth starting? Respond to my poll here🚀

For more useful and innovative tips and tricks, Let's connect on Medium

Comments 0 total

    Add comment