Skip to content

Undoing Changes in Git

Git is a powerful version control system, but sometimes you make changes you want to undo. Whether it's a file you accidentally staged, a commit you regret, or a need to revert to a previous state, Git provides tools to help. This section explains how to undo changes in Git, covering unstaging, undoing commits, and using soft and hard resets, as well as reverting to a specific commit hash.

1. Undoing Changes in the Working Directory (Untracked or Modified Files)

Before changes are staged or committed, they exist in your working directory. These are either untracked files (new files Git isn't tracking) or modified files (tracked files with changes).

  • Discard changes to a modified file: If you edited a tracked file but want to discard those changes, use:
git restore <file-name>

Example: git restore index.html discards all changes to index.html since the last commit.

  • Remove untracked files: For new, untracked files you want to delete:
git clean -f

Use git clean -n first to preview what will be removed. Combine with -d (git clean -fd) to remove untracked directories too.

Note: Be careful—these commands permanently discard changes. Always double-check with git status to see what's in your working directory.

2. Undoing Changes from the Staging Area

The staging area holds changes you've marked for the next commit using git add. If you accidentally stage a file, you can unstage it without losing your changes.

  • Unstage a file: To remove a file from the staging area but keep its changes in the working directory:
git reset <file-name>

Example: git reset index.html unstages index.html, so it’s no longer included in the next commit.

  • Unstage all staged files: To unstage everything:
git reset .

After unstaging, the changes return to your working directory. You can then edit them further.

3. Undoing Commits

Commits are snapshots of your project saved in Git. If you make a commit and realize it was a mistake, you can undo it. The approach depends on whether the commit has been shared (pushed to a remote repository) or is still local.

a. Undoing the Last Commit (Soft Undo)

If you want to undo the last commit but keep the changes in your working directory or staging area, use a soft reset:

git reset --soft HEAD~1
  • What it does: Removes the last commit but keeps all changes from that commit in your staging area or working directory.
  • Use case: You committed too early and want to edit the changes before recommitting.
  • Example: After git commit -m "WIP", run git reset --soft HEAD~1. The commit is gone, but your changes are ready to be recommitted with git commit.

b. Undoing the Last Commit and Changes (Hard Undo)

If you want to completely discard the last commit and its changes, use a hard reset:

git reset --hard HEAD~1
  • What it does: Deletes the last commit and all its changes, restoring your project to the state of the previous commit.
  • Use case: You made a mistake in the last commit and want to erase it entirely.
  • Caution: This permanently deletes changes, so ensure you don’t need them.

c. Undoing Multiple Commits

To undo multiple commits, specify how many commits to go back using HEAD~n, where n is the number of commits.

  • Soft reset example:
git reset --soft HEAD~2

This undoes the last two commits but keeps their changes in your working directory/staging area.

  • Hard reset example:
git reset --hard HEAD~2

This deletes the last two commits and all their changes.

Note: If you’ve pushed these commits to a remote repository (like GitHub), avoid hard resets, as they rewrite history and can cause issues for collaborators. Instead, use git revert (explained below).

4. Reverting to a Specific Commit Hash

Every commit in Git has a unique commit hash (a long string like a1b2c3d...). You can find hashes using:

git log --oneline

This shows a list of commits with their hashes and messages. To revert your project to a specific commit:

  • Soft reset to a commit hash:
git reset --soft <commit-hash>

Example: git reset --soft a1b2c3d undoes all commits after a1b2c3d, keeping their changes in your working directory/staging area.

  • Hard reset to a commit hash:
git reset --hard <commit-hash>

Example: git reset --hard a1b2c3d deletes all commits and changes after a1b2c3d, restoring your project to that commit’s state.

Caution: Hard resets are destructive. Always back up important work (e.g., by creating a new branch with git branch backup) before using them.

5. Using git revert for Safer Undoing

If you’ve pushed commits to a shared repository, resetting can cause problems because it rewrites history. Instead, use git revert to create a new commit that undoes a previous one:

git revert <commit-hash>
  • What it does: Creates a new commit that reverses the changes of the specified commit.
  • Use case: You want to undo a commit without altering the project’s history, especially in collaborative projects.
  • Example: git revert a1b2c3d creates a new commit that cancels the changes from commit a1b2c3d.

You can revert multiple commits by specifying a range or running git revert multiple times.

6. Key Differences: Soft vs. Hard Reset

  • Soft Reset (git reset --soft):
  • Keeps changes in your working directory or staging area.
  • Useful for redoing commits or combining changes into a new commit.
  • Does not delete your work.

  • Hard Reset (git reset --hard):

  • Deletes commits and their changes permanently.
  • Restores your project to the exact state of the specified commit.
  • Use with caution, as changes are lost.

7. Tips for Beginners

  • Check your status: Always run git status to see what’s in your working directory and staging area.
  • View commit history: Use git log --oneline to find commit hashes and understand your project’s history.
  • Backup before resetting: Create a new branch (git branch backup) before destructive commands like git reset --hard.
  • Practice in a test repository: If you’re new to Git, experiment in a non-critical project to build confidence.
  • Avoid rewriting shared history: Use git revert instead of git reset for commits pushed to a remote repository.

8. Example Workflow

Let’s say you:

  1. Edited index.html and staged it (git add index.html).
  2. Committed it (git commit -m "Update index").
  3. Realized it was a mistake.

Here’s how you can undo:

  • Unstage: git reset index.html (keeps changes in working directory).
  • Discard changes: git restore index.html (removes changes to index.html).
  • Undo commit: git reset --soft HEAD~1 (keeps changes for editing) or git reset --hard HEAD~1 (deletes commit and changes).
  • Revert pushed commit: git revert <commit-hash> (creates a new commit to undo it).

By understanding these commands, you can confidently manage and undo changes in Git!