The Ultimate Guide to Undoing Git Commits

Lineserve TeamLineserve Team
·
8 min read

The Ultimate Guide to Undoing Git Commits: A Comprehensive Tutorial

Git is an incredibly powerful version control system, but with great power comes great responsibility – and sometimes mistakes. Committing changes you didn’t intend to keep is a common occurrence for developers at all levels. This comprehensive guide will walk you through all the ways to undo commits in Git, explain the underlying concepts, and help you choose the right approach for your situation.

Understanding Git Commits

Before learning how to undo commits, it’s crucial to understand what a commit actually is in Git’s architecture.

A Git commit is a snapshot of your repository at a specific point in time. Each commit contains:

  • A unique SHA-1 hash identifier (like e2e9f5d8c)
  • A reference to its parent commit(s)
  • The author and timestamp
  • A commit message
  • A snapshot of all files in the repository at that moment

Commits form a directed acyclic graph (DAG) where each commit points back to its parent(s). This structure enables Git’s powerful version control capabilities.

When You Might Need to Undo Commits

Common scenarios where you’d want to undo commits include:

  1. Committing with the wrong files staged
  2. Writing an incorrect commit message
  3. Committing to the wrong branch
  4. Realizing the changes introduce bugs
  5. Wanting to split a commit into smaller ones
  6. Needing to reorganize commit history before pushing

Method 1: git reset – The Most Common Undo Tool

The git reset command is your primary tool for undoing local commits. It comes in three flavors:

Soft Reset (--soft)

git reset --soft HEAD~1
  • What it does: Moves the HEAD pointer back to the specified commit (in this case, one commit back), but keeps all changes staged
  • When to use: When you want to redo the commit with different files or a new message
  • Effect: The commit disappears from history, but all changes remain in the staging area
  • Safety: Very safe – no work is lost

Mixed Reset (--mixed or default)

git reset HEAD~1
# Or equivalently:
git reset --mixed HEAD~1
  • What it does: Moves HEAD back and unstages changes, but keeps them in your working directory
  • When to use: When you want to uncommit and unstage changes, but keep them for modification
  • Effect: Commit is removed, changes are preserved but unstaged
  • Safety: Safe – changes remain in your working tree

Hard Reset (--hard)

git reset --hard HEAD~1
  • What it does: Moves HEAD back and discards all changes from the target commit onward
  • When to use: When you want to completely remove commits and all associated changes
  • Effect: Commit and all changes are permanently removed
  • Safety: Dangerous – changes are lost unless you have them stashed or backed up

Understanding HEAD~ and HEAD^

The notation HEAD~1 refers to “one commit before HEAD”. You can also use:

  • HEAD~n – n commits back in the first parent lineage
  • HEAD^n – the nth parent (useful for merge commits)

For example:

  • HEAD~3 – three commits back
  • HEAD^2 – second parent of a merge commit

Method 2: git revert – The Safe Alternative

While git reset rewrites history, git revert creates a new commit that undoes the changes:

git revert HEAD
  • What it does: Creates a new commit that reverses the changes from the specified commit
  • When to use: When commits have been shared with others (already pushed)
  • Effect: History remains intact, but a new “undo” commit is added
  • Safety: Very safe – doesn’t rewrite history

You can revert multiple commits:

git revert HEAD~3..HEAD

This reverts the last three commits in order from oldest to newest.

Method 3: git commit --amend – Fixing the Last Commit

If you just need to modify the most recent commit:

git add forgotten_file.txt
git commit --amend
  • What it does: Combines staged changes with the previous commit and lets you edit the commit message
  • When to use: When you forgot to include files or need to change the commit message
  • Effect: Replaces the last commit with a new one
  • Safety: Safe for local commits, dangerous if already pushed

Method 4: git rebase -i – Interactive History Editing

For more sophisticated history rewriting:

git rebase -i HEAD~5

This opens an interactive rebase session showing the last 5 commits. You can then:

  • pick – keep the commit as is
  • reword – keep changes but edit message
  • edit – stop to amend the commit
  • squash – combine with previous commit
  • fixup – like squash but discard message
  • drop – remove the commit entirely

Method 5: git stash – Temporary Storage

If you want to temporarily set aside changes:

git stash
# Later...
git stash pop
  • What it does: Temporarily shelves changes so you can return to a clean working directory
  • When to use: When you need to switch contexts but aren’t ready to commit
  • Effect: Changes are saved in the stash stack
  • Safety: Generally safe, but stashes can be lost if not reapplied

Advanced Scenarios

Undoing a Merge Commit

git revert -m 1 <merge-commit-hash>

The -m 1 specifies which parent branch to consider as the main line.

Recovering Lost Commits

If you reset too far, you can often recover using:

git reflog
git reset --hard HEAD@{1}

The reflog keeps track of all reference changes (like HEAD movements) for about 30 days by default.

Splitting a Commit

Using interactive rebase:

  1. Mark the commit with edit
  2. When rebase stops:
   git reset HEAD~
   git add -p  # selectively stage changes
   git commit -m "First part"
   git add .
   git commit -m "Second part"
   git rebase --continue

Best Practices and Warnings

  1. Never rewrite public history: Only use history-rewriting commands (reset, amend, rebase) on commits that haven’t been pushed yet.
  2. Backup before destructive operations: Before using --hard reset or similar commands, consider:
   git stash
   # or
   git branch backup_branch
  1. Understand the implications: Each undo method has different consequences:
  • reset changes history
  • revert adds new history
  • amend replaces commits
  1. Communicate with your team: If you must rewrite pushed history, coordinate with collaborators who may have based work on the old commits.

Visualizing Undo Operations

Let’s visualize a simple scenario with three commits:

A -- B -- C (HEAD)
  • git reset --soft B: Now HEAD points to B, C’s changes are staged
  • git reset B: HEAD points to B, C’s changes are unstaged but in working directory
  • git reset --hard B: HEAD points to B, C’s changes are discarded
  • git revert C: Creates new commit D that undoes C: A — B — C — D

Common Mistakes and How to Avoid Them

  1. Accidentally deleting work with --hard:
  • Solution: Always check git status before resetting
  • Recovery: Check git reflog for the lost commit
  1. Amending pushed commits:
  • Solution: Only amend local commits
  • Recovery: Push with --force if absolutely necessary (with team coordination)
  1. Reverting merge commits incorrectly:
  • Solution: Use -m to specify parent
  • Recovery: May need to redo the merge

Frequently Asked Questions

Q: What’s the difference between git reset and git revert?
A: reset moves the branch pointer and can discard commits, while revert creates new commits that undo changes without altering history.

Q: Can I undo a git reset --hard?
A: If you just did it, check git reflog to find the previous HEAD position. Otherwise, you may need file recovery tools.

Q: How do I undo multiple commits?
A: Specify how many commits to undo: git reset HEAD~3 for the last three commits.

Q: What if I already pushed my changes?
A: Use git revert instead of reset. If you must rewrite history, you’ll need to force push (git push --force) and coordinate with your team.

Q: How do I remove a file from a commit without undoing the whole thing?
A: Use:

git rm --cached <file>
git commit --amend

Git Undo Cheat Sheet

CommandUse CaseEffectSafety
git reset --soft HEAD~1Redo last commitUndo commit, keep changes stagedSafe
git reset HEAD~1Uncommit and unstageUndo commit, keep changes unstagedSafe
git reset --hard HEAD~1Completely remove last commitDiscard commit and changesDangerous
git revert HEADUndo public commitCreate inverse commitVery safe
git commit --amendFix last commitReplace last commitSafe if local
git rebase -iEdit multiple commitsRewrite historyDangerous if pushed
git stashTemporary storageShelve changesGenerally safe

Real-World Examples

Example 1: Wrong Files Committed

Situation: You committed changes to file1.js but forgot to include file2.js.

Solution:

git add file2.js
git commit --amend

Example 2: Accidentally Committed to Main

Situation: You made commits on main but meant to work on a feature branch.

Solution:

git branch feature-branch
git reset --hard origin/main

Example 3: Need to Split a Large Commit

Situation: One commit contains too many unrelated changes.

Solution:

git rebase -i HEAD~2
# Mark commit with 'edit'
git reset HEAD~
git add -p  # Stage changes interactively
git commit -m "First part"
git add .
git commit -m "Second part"
git rebase --continue

Conclusion

Mastering Git’s undo capabilities is essential for efficient version control. The key takeaways are:

  1. Use reset for local undo operations
  2. Use revert for public commits
  3. amend is great for quick fixes to the last commit
  4. Interactive rebase offers powerful history editing
  5. Always be cautious with history-rewriting operations
  6. The reflog is your safety net for many mistakes

Remember that while Git provides many ways to undo changes, prevention is often better than cure. Get in the habit of:

  • Making small, focused commits
  • Reviewing changes with git diff --cached before committing
  • Using branches liberally for experimental work

With these tools and practices, you can work confidently knowing you can recover from almost any Git mishap.

Share:

Related Guides

Automating JNLP Downloads with PowerShell Using Session Cookies

When managing remote servers or BMC interfaces, some resources such as JNLP (Java Network Launch Protocol) files require authentication via cookies and session handling. Manually downloading these files can be cumbersome. PowerShell provides a way to automate this process using web sessions and cookie management. Creating a Persistent Web Session A web session in PowerShell [&hellip;]

Stephen Ndegwa
·

Complete Guide to Downloading Files with PowerShell

Introduction PowerShell provides powerful tools for downloading files from web servers, with Invoke-WebRequest being the primary cmdlet for making HTTP requests. This guide covers everything from basic downloads to advanced scenarios involving authentication, cookies, and custom headers. Basic File Downloads Simple Download The most straightforward way to download a file: Download with Progress Bar PowerShell [&hellip;]

Stephen Ndegwa
·

The Complete Guide to Installing StorCLI on Linux and Windows

StorCLI (Storage Command Line Tool) is Broadcom&#8217;s powerful command-line utility for managing LSI MegaRAID and PRAID controllers. Whether you&#8217;re managing hardware RAID arrays on servers or workstations, StorCLI provides comprehensive control over your storage infrastructure. This guide will walk you through the complete installation process on both Linux and Windows systems. What is StorCLI? StorCLI [&hellip;]

Stephen Ndegwa
·