As developers, we often find ourselves needing to remove commits from Git history while retaining the associated code changes in our local repositories. This comes up frequently enough that understanding how to safely delete commits with git reset is an important skill.
In this comprehensive guide, we will dig into common scenarios where commit deletion is useful, how Git stores commits under the hood to keep changes safe, the critical difference between reset and revert, and best practices developers should follow when rewriting commit history in shared repositories.
When Would I Need to Delete Commits But Keep Changes?
Here are some of the most common reasons you may need to rewrite Git history by removing commits, while keeping the changes in your working tree intact:
1. Accidentally Committed Sensitive Data
One all too familiar scenario is realizing you accidentally committed API keys, database credentials, or other sensitive information. In a Verizon report, misconfigurations exposing data caused nearly 22% of breaches studied. Thankfully, Git‘s commit deletion capabilities enable undoing these mistakes before pushing credentials to remote repositories for all to see!
2. Committed to Wrong Branch
Most developers use topic or feature branches during development. Despite our best intentions, it‘s easy to find yourself committing directly to main or another long-running branch by mistake. Rather than convoluted history of merging experimental work back out, deleting the commit with git reset leads to a cleaner project history.
3. Botched Commit Messages
Well-crafted commit messages are vital for understanding changes in Git‘s history. When messages fail to summarize modifications accurately, other developers may misunderstand the purpose or extent of a change. By deleting and re-committing with an improved message, you enhance the ongoing documentation value Git provides.
4. Premature Commits of Incomplete Work
To save progress or snapshot things at a certain point, developers may commit changes that are still in flux or not yet tested. Rather than leaving these intermediate commits polluting history forever, deleting via git reset and re-committing when the work is production-ready improves the commit timeline‘s signal-to-noise ratio.
In all the cases above, the ability to remove commits while keeping uncommitted changes comes in extremely handy!
How Does Git Store Data to Keep Changes Safe After Resetting?
To understand how removing commits allows preserving local changes, we need to learn about Git‘s underlying content storage model.

In Git, commits serve as snapshots of your entire codebase at points in the project‘s history. Rather than storing file diffs explicitly, Git implements an elegant object model:
- Blobs: Capture file contents as they exist in a certain version
- Trees: Represent folder structures, storing references to blob and tree objects
- Commits: Contain metadata like messages, author info, and a tree capturing the state of files in that snapshot
This content-addressable object model means file contents are stored just once, with commits referencing trees pointing at those blob objects containing file contents.
By separating file data from history, Git enables committing and resetting freely without changing anything about the way code state is stored! Since trees and blobs remain after discarding commits referencing them, your local changes persist safely.
Understanding this content storage model helps explain how removing commits leaves working tree modifications intact.
Git Reset vs Git Revert: What‘s the Difference?
Given that deleting commits with git reset is so useful, you might wonder why the git revert command even exists. While the end result is similar, there is a critical difference all developers must comprehend:
| Operation | Rewrites Existing History |
Undoes Changes | Preserves Local Modifications |
Safe for Public Commit History |
|---|---|---|---|---|
| git reset | Yes | Yes | Yes | No |
| git revert | No | Yes | N/A | Yes |
Resetting actually erases commits from the existing timeline, while reverting introduces new commits undoing the specified changes. Although both remove the changes in question from the codebase moving forward, reset rewrites history shared with others while revert preserves the shared timeline.
This has critical implications when other developers have cloned your repository or you‘ve pushed commits to remote servers. Let‘s look at how to use these commands properly when dealing with public commit history.
Best Practices: Deleting Commits in Public History
Although removing commits with git reset is simple and keeps local changes safe, you must exercise great caution when rewriting commits that exist on shared remote repositories.
Rewriting public history can lead to remote syncing issues, data loss, and confusion for collaborators depending on reset usage. Instead, you should prefer reverting public commits rather than resetting directly.
However, as long as you force push properly according to team policies, Git does enable overwriting public history safely when necessary:
1. Get Approval From Your Team
Never forcibly rewrite a repository‘s publicly shared history without first getting approval from collaborators. Communicate why removing the commit is critical to avoid surpising teammates.
2. Force Push Your Reset Carefully
After locally removing commits with git reset, you must force push the truncated history to the remote to sync:
git push --force origin main
This overwrites the remote branch with your rewritten, shortened local history. Handle this atomically and warn users before force pushing.
3. Verify Integrity, Then Notify Users
Once the remote branch is force updated, check that committed file blobs still exist as expected in the shared repository. Finally, let collaborators know they need to rebase any dependent branches to avoid merging issues.
By following this protocol for publicly resetting, you overwrite historical commits safely while keeping teammates aware of the changes.
Key Takeaways: Safely Deleting Commits in Git
Given how often developers need to remove accidental, premature or incorrect commits, understanding how to leverage git reset properly is a critical skill. Here are some best practices to recap:
- Locally, feel free to delete commits via reset as needed to keep history clean. Changes safely persist in blobs.
- Publicly, revert commits to avoid rewriting history shared with others.
- If team agrees, always force push atomically and verify remote integrity after public resets.
- Unlike resetting, reverting introduces new commits undoing unwanted changes.
- Resetting actually moves branch refs backwards, deleting commits after that point.
With this conceptual foundation on removing commits like a pro, you can avoid common mishaps and enhance your team‘s Git commit history hygiene practices. Mastering both reset and revert helps modern development teams progress faster by allowing history redaction while keeping changes safe locally.


