# When a Secret Leaks into Git: Recovering from an Accidental Secret Commit

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.

* * *

## The Problem

When pushing my branch, GitHub returned:

```markdown
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.

* * *

## Common Misconception

It's easy to assume that replacing the secret with:

```markdown
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.

* * *

## The Solution: Rewrite Git History

Since this was a brand-new branch that had never been pushed successfully, rewriting history was the easiest and safest option.

### 1\. Identify the Offending Commit

GitHub already provided the commit hash:

```markdown
commit: 0f76c9a...
```

Inspect the commit:

```markdown
git show 0f76c9a -- <affected-file>
```

* * *

## 2\. Determine How Far the Secret Has Spread

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:

```bash
git log -p --all
```

Or inspect the history of the affected file:

```bash
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.

## 3\. Start an Interactive Rebase

In this article, I'll use Interactive Rebase by starting from the commit immediately before the earliest affected commit.

For example

```bash

git rebase -i <base-commit>
```

change

```plaintext

pick 0f76c9a ...
```

to:

```plaintext

edit 0f76c9a ...
```

And continue the cleanup process.

* * *

## 4\. Amend the Commit

Replace the secret with a placeholder:

```markdown
APPLICATION_SECRET=<YOUR_SECRET>
```

```markdown
git add <affected-file>
```

```markdown
git commit --amend --no-edit
```

Continue the rebase:

```markdown
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-empty`
> 
> Otherwise, please use:
> 
> `git rebase --skip`

* * *

## 5\. Verify the Secret Has Been Completely Removed

Before pushing, verify that the secret has been removed from the entire branch history.

Start by checking the rewritten commit

```markdown
git show <new-commit-hash> -- <affected-file>
```

However, if the secret appeared in multiple commits, this check alone is not sufficient.

### Verify All Affected Commits

Review each commit that previously contained the secret:

```markdown
git show <commit-hash> -- <affected-file>
```

Confirm that the secret has been replaced with placeholders or removed entirely.

### Verify the Entire Branch History

Search the branch history for the secret value:

```markdown
git log -p --all
```

Or search for the affected variable:

```markdown
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.

* * *

### 6\. Push Again

Since history was rewritten:

```markdown
git push --force-with-lease
```

The push should now succeed.

* * *

## Lessons Learned

*   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.
    

* * *

## Final Thoughts

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.
