Undoing Mistakes in Git

Mistakes happen, even when using Git. Fortunately, Git provides several ways to undo changes depending on how far along they are in the workflow. This article will cover different scenarios and how to fix them, starting from uncommitted changes, moving on to local commits, and finally addressing changes that have been pushed to a remote repository.

Undoing Mistakes in Git

Undoing Uncommitted Changes

If you’ve made changes to files but haven’t committed them yet, there are a few ways to undo them depending on whether you want to discard them entirely or just revert some modifications.

1- Discard Changes in a Tracked File

If you’ve modified a tracked file and want to undo the changes:

git restore <file>

This resets the file to its last committed state. However, this does not work for new files that are not yet tracked.

👉 In VS Code source control panel, you can do this by clicking the “Discard Changes” button beside the file name.

2- Discard All Changes in the Working Directory

To discard all modifications in your working directory:

git restore .

This resets all tracked files to their last committed state, so use it with caution.

👉 In VS Code source control panel, you can do this by clicking the “Discard All Changes” button in the “Changes” panel.

3- Remove Untracked Files

To delete untracked files:

git clean -f

This will only remove the untracked files, but won’t affect the changed files that are tracked.

To also remove untracked directories:

git clean -fd

Be careful with this command, as it permanently deletes files that Git isn’t tracking.

Undoing Local Commits

If you’ve already committed changes but haven’t pushed them, there are several options depending on what you want to do.

1- Undo the Last Commit (Keep Changes in Staging Area)

If you want to undo the last commit but keep the changes staged:

git reset --soft HEAD~1

This moves the HEAD pointer back one commit while keeping your changes staged.

👉 In VS Code source control panel, you can do this by clicking the three dots button and clicking “Undo Last Commit” under the “Comit” menu.

Undo the Last Commit

2- Undo the Last Commit (Move Changes Back to Working Directory)

If you want to undo the last commit and move the changes back to the working directory:

git reset --mixed HEAD~1

This keeps your modifications but removes them from the staging area.

3- Completely Remove the Last Commit

If you want to erase the last commit and discard all changes:

git reset --hard HEAD~1

Be cautious—this action is irreversible if you don’t have backups.

4- Revert to a Commit That’s Not the Last One

If you want to reset your branch to a specific commit (not necessarily the last one), use:

git reset --hard <commit-hash>

This will remove all commits after the specified commit, including uncommitted changes.

To keep the changes unstaged instead of discarding them, use:

git reset --mixed <commit-hash>

To keep the changes staged:

git reset --soft <commit-hash>

5- Undo a Specific Commit but Keep Later Commits

You can use git revert to create a new commit that undoes the changes from a previous commit while preserving the project’s history. Unlike git reset, which alters commit history, git revert safely applies the inverse of a commit and adds it as a new commit. This is useful for undoing changes in a collaborative environment without rewriting history.

git revert <commit-hash>

This generates a new commit that negates the effects of the specified commit, keeping history intact.

Note: VS Code opens a window for the commit message. It uses Vim by default. To save and close the commit message in Vim follow these steps:

  1. Press Esc (to ensure you’re in normal mode).
  2. Type :wq (this stands for “write and quit”).
  3. Press Enter.

Alternatively, if you want to cancel the revert, use:

  1. Press Esc.
  2. Type :q! (this means “quit without saving”).
  3. Press Enter.

6- Restore a Specific File to a Specific Commit

If you want to restore a single file to a previous commit without affecting other changes, use:

git restore --source <commit-hash> <file>

This will revert the file to its state in the specified commit while keeping the rest of the repository unchanged. You need to commit the restored file if you want to save the change.

Undoing Pushed Commits

If you have already pushed commits to a remote repository, undoing them becomes more complex. The right approach depends on whether others have already pulled those changes.

1- Undo the Last Commit (Before Others Have Pulled)

If you’ve pushed a commit and want to undo it before anyone else has pulled it:

git reset --hard HEAD~1

Then force push to update the remote branch:

git push --force

⚠️ Warning: This rewrites history and can cause issues for others working on the same branch.

2- Undo a Specific Commit Without History Rewriting

If you need to undo a commit but want to keep history clean:

git revert <commit-hash>

Then push the revert commit:

git push

This is the safer option when collaborating with others.

Conclusion

Git provides powerful tools to undo mistakes at various stages, from uncommitted changes to pushed commits. The key is choosing the right method depending on the situation:

  • Use restore, reset, or clean for uncommitted changes.
  • Use reset (soft, mixed, or hard) or revert for local commits.
  • Use revert or force-pushing (push –force) cautiously when undoing remote commits.

Understanding these commands will help you navigate mistakes confidently and keep your repository clean and manageable.