How to Remove Commits from Git History Safely

It’s not uncommon to accidentally commit unintended changes or confidential data to a Git repository—either local or remote. Fortunately, Git includes powerful tools for rewriting commit history. These allow you to clean up mistakes, remove sensitive content, and simplify your commit logs. This tutorial walks you through effective methods for removing Git commits from both local and shared repositories.

Quick Reference Guide

Below is a summary of commonly used commands:

# Show compact commit history
$ git log --oneline

# Undo most recent commit (remove changes)
$ git reset --hard HEAD~1

# Delete a specific commit via interactive rebase
$ git rebase -i HEAD~N

# Retrieve removed commit via reflog
$ git reflog
$ git reset --hard HEAD@{n}

# Wipe a file or folder from all commit history
$ git filter-repo --path <path> --invert-paths

Viewing Commit Logs in Git

You can review your commit history using Git in either a concise or detailed format. This helps in identifying and managing specific commits.

Command Syntax

  • git log: Lists all commits with hash, author, timestamp, and message.
  • --oneline: Displays each commit on a single line using hash and message.

Compact History View

Example Output:

e2369629 removed requirement.txt file
2e39f29b Used Poetry for dependency management
2f7490ae modularized my code
de4c0fb8 Updated the ReadME file
39b41a37 Concluded unit testing
1acecd8c minor
5a1f681e Added a dockerfile, updated the readme and added a requirements.txt file
97c43fa3 remove comm.md
1f20c89f first commit

Full Commit Log View

Example Output:

commit e23696290557c029add5490d81bb305dc506f61c
Author: johndoe <johndoe@gmail.com>
Date:   Sun Sep 1 20:03:36 2024 +0100

    removed requirement.txt file

commit 2e39f29b49447219bc32a7fbdd6e8a5834b83911
Author: johndoe <johndoe@gmail.com>
Date:   Sun Sep 1 20:00:50 2024 +0100

    Used Poetry for dependency management

Use arrow keys to scroll and press q to quit the view.

Undoing the Last Commit

You can undo the most recent commit using git reset. Depending on your choice of reset mode, changes can be preserved, unstaged, or discarded.

Command Syntax

git reset [--soft | --mixed | --hard] HEAD~N

  • --soft: Retains staged changes.
  • --mixed: Unstages changes, keeps working directory intact.
  • --hard: Erases all local changes completely.

Examples

Keep staged:

Unstage:

$ git reset --mixed HEAD~1

Discard all changes:

Removing a Specific Commit

If you need to erase a commit that’s not the latest, use an interactive rebase to select and delete it manually.

Command Syntax

Example: Editing the Last 8 Commits

pick 5fce205e Enhanced the ReadMe
pick 8404786f minor
pick f5879bb9 minor
pick c26abc6b minor
pick b1db91c2 minor
pick f18e3944 minor
pick ba58ebeb Used Poetry for dependency management
pick 8169d159 removed requirement.txt file

Steps:

  • Press i to enter insert mode.
  • Change pick to drop for the commit you want to remove.
  • Press Esc, type :wq, then press Enter.

Rebase confirmation message:

Successfully rebased and updated refs/heads/main.

Recovering Deleted Commits

If a commit gets lost due to a reset or rebase, you might be able to recover it using Git’s reflog, which tracks past HEAD states.

Recovery Commands

  • After hard reset: git reset --hard HEAD@{n}
  • After mixed reset: git reset --mixed HEAD@{n}
  • After soft reset: git reset --soft HEAD@{n}

Viewing Reflog Entries

Example Output:

7a9a8b2f HEAD@{0}: rebase (finish): returning to refs/heads/main
7a9a8b2f HEAD@{1}: rebase (pick): Used Poetry for dependency management
59c2d68e HEAD@{2}: rebase (start): checkout HEAD~8
8dbe3b9a HEAD@{3}: reset: moving to HEAD~1

View Commit Content Before Recovery

Reset to Reflog Entry

$ git reset --hard HEAD@{3}

Reset to Specific Commit Hash

$ git reset --hard 8dbe3b9a

Preview the commit:

Completely Deleting Files from Git History

To exclude a file or folder from all previous commits, rewriting history is necessary. Simply removing it from current staging doesn’t affect the past.

Remove from Future Commits

$ git rm --cached <path-to-file>
$ git rm -r --cached <path-to-directory>

Erase from Entire History (Recommended)

$ git filter-repo --path <path> --invert-paths

Using git filter-repo for History Rewriting

git filter-repo is the improved alternative to the older git filter-branch command. It offers better performance, reliability, and simplicity for permanently erasing files or folders from Git history. This tool is not bundled with Git by default and must be added separately.

Step-by-Step: Removing Files and Directories with git filter-repo

Install the Tool

$ pip3 install git-filter-repo

Create a Backup of Your Repository

$ cp -r <your-repository-name> <your-repository-name-backup>

Erase a Specific File from Commit History

$ git filter-repo --path <path-to-file> --invert-paths

Confirm the File No Longer Exists in Any Commit

$ git log --all -- <path-to-file>

If there’s no output, the removal was successful.

Erase a Directory from Commit History

$ git filter-repo --path <path-to-directory> --invert-paths

Confirm the Directory is Gone from History

$ git log --all -- <path-to-directory>

No output means the directory has been fully purged from the commit history.

Final Thoughts

This tutorial covered several approaches for modifying Git commit history. You learned how to reverse recent commits using git reset, remove particular commits through interactive rebase, and completely wipe files or folders with git filter-repo. Additionally, we looked at how to retrieve deleted commits using git reflog.

Important: When collaborating in shared environments, it’s better to use git revert to undo changes without rewriting history. Directly altering commit logs should be reserved for local or non-public branches, as it can cause confusion or conflicts if misused on published branches.

Source: vultr.com

Create a Free Account

Register now and get access to our Cloud Services.

Posts you might be interested in: