When a Secret Leaks into Git: Recovering from an Accidental Secret Commit
How to Fix a GitHub Push Protection Error.

Search for a command to run...
How to Fix a GitHub Push Protection Error.

No comments yet. Be the first to comment.
Balancing security and development speed in role-based access design

The XY problem is a communication issue that often arises in software development. It occurs when someone seeking help focuses on their attempted solution (Y) rather than the actual problem (X) they’re trying to solve. It often plays out like this: ...

Encryption is the foundation of secure communication and data storage. At its core, it scrambles information with a cryptographic key so that only authorized parties can read it. Decryption then reverses this process, restoring the original data. But...

How to Use JSON for Better Site Property Management in OutSystems

Recently, I encountered a GitHub Push Protection error while pushing a new feature branch. GitHub rejected the push because a secret had been accidentally committed to the repository.
While the fix sounded simple at first ("just remove the secret from the file"), I quickly learned that GitHub scans the entire commit history being pushed, not only the latest version of the file.
Here's how I resolved it.
When pushing my branch, GitHub returned:
GH013: Repository rule violations found
Push cannot contain secrets
commit: 0f76c9a...
path: <affected-file>
GitHub detected a secret in a committed configuration file (GH013)
At this point, I had already removed the secret from the file, but the push was still blocked.
Why?
Because the secret was still present in the Git history.
It's easy to assume that replacing the secret with:
APPLICATION_SECRET=<YOUR_SECRET>
and committing again will solve the issue. Unfortunately, it doesn't.
GitHub Push Protection scans:
Current file contents
Commit history included in the push
If any commit being pushed contains the secret, the push will still be rejected.
Since this was a brand-new branch that had never been pushed successfully, rewriting history was the easiest and safest option.
GitHub already provided the commit hash:
commit: 0f76c9a...
Inspect the commit:
git show 0f76c9a -- <affected-file>
Before rewriting history, determine whether the secret exists in a single commit or multiple commits.
GitHub usually reports one offending commit, for example:
commit: 0f76c9a...
However, the same secret may also appear in other commits.
Search your Git history to find every occurrence:
git log -p --all
Or inspect the history of the affected file:
git log -p --all -- <affected-file>
Once you know where the secret exists:
Single commit: Edit that commit using Interactive Rebase.
Multiple commits: Rewrite every affected commit. For more extensive cases, consider tools such as git filter-repo.
Understanding the scope first helps you choose the right cleanup approach.
In this article, I'll use Interactive Rebase by starting from the commit immediately before the earliest affected commit.
For example
git rebase -i <base-commit>
change
pick 0f76c9a ...
to:
edit 0f76c9a ...
And continue the cleanup process.
Replace the secret with a placeholder:
APPLICATION_SECRET=<YOUR_SECRET>
git add <affected-file>
git commit --amend --no-edit
Continue the rebase:
git rebase --continue
💡
During the rebase, Git may determine that a commit no longer contains any changes because they were already applied during earlier edits or conflict resolution.
Example Git message
This commit is now empty.If you wish to keep it, use:
git commit --allow-emptyOtherwise, please use:
git rebase --skip
Before pushing, verify that the secret has been removed from the entire branch history.
Start by checking the rewritten commit
git show <new-commit-hash> -- <affected-file>
However, if the secret appeared in multiple commits, this check alone is not sufficient.
Review each commit that previously contained the secret:
git show <commit-hash> -- <affected-file>
Confirm that the secret has been replaced with placeholders or removed entirely.
Search the branch history for the secret value:
git log -p --all
Or search for the affected variable:
git log -p --all -- <affected-file>
The goal is to confirm that no commit being pushed still contains the secret. Only proceed with the push once you have verified that the secret has been fully removed from the Git history.
Since history was rewritten:
git push --force-with-lease
The push should now succeed.
Never commit real secrets, even temporarily.
Removing a secret from the latest version of a file isn't enough. It must also be removed from the Git history.
Treat any exposed secret as compromised and rotate it immediately.
GitHub Push Protection may feel frustrating at first, but it's an effective safeguard against accidentally exposing sensitive credentials.
The key takeaway is simple:
If a secret has been committed, don't just remove it from the file. Remove it from the Git history as well.
Spending a few minutes cleaning up Git history is far easier than dealing with a leaked credential later.