Learn Git - Repository Security & Branch Protection Rules
Episode 13 of 21

Learn Git - Repository Security & Branch Protection Rules

Secure your repository with branch protection rules on main, understand the danger of leaked API keys and database credentials, make use of GitHub Secret Scanning and Dependabot Alerts, and learn the emergency steps if a secret is already committed.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 12 we learned to manage work with GitHub Issues. Now imagine your team is large: dozens of developers can push to main, and some of them forget to write PR descriptions or put passwords in configuration files. Without agreed-upon security, a single commit can break production or leak company credentials.

This episode covers two sides of repository security: enforcing rules through Branch Protection Rules so code does not randomly enter main, and preventing and handling secret leaks — API keys, private keys, or database credentials — using GitHub Secret Scanning and Dependabot Alerts. At the end, we discuss the emergency steps if a secret has already been committed.

The Danger of Secret Leakage

A secret is information that grants access: API keys, tokens, SSH private keys, database usernames and passwords, even cloud credentials. Once a secret enters a commit and is pushed, it is stored forever in Git history — even if the file is deleted in the next commit, the secret can still be found in the history by anyone with repository access.

The danger multiplies in public repositories: attackers and scanner bots constantly scan GitHub for secret patterns. Once caught, cloud accounts, databases, or other services can be controlled by someone else — often within minutes. That is why a secret leak is not a "small problem to clean up later", but an incident that must be taken seriously.

Preventing Secrets from Entering Commits

The first and cheapest rule is prevention: never write secrets in files tracked by Git. Use a .env file listed in .gitignore, and inject secret values via environment variables at deployment time.

Example of a safe env file
# .env.local — tidak boleh di-commit
 
DATABASE_URL=postgres://user:pass@db.example.com:5432/app
 
API_KEY=sk_live_1234567890abcdef

Make sure .gitignore contains the following entries before running git add .:

Ignoring env files
# .gitignore
.env
.env.local
.env.production

GitHub Secret Scanning & Dependabot Alerts

Even when you are careful, humans still make mistakes. GitHub provides two layers of automated defense:

Secret Scanning — scans the repository (and commit history) for secret patterns from thousands of providers: AWS, Google Cloud, GitHub tokens, Stripe, and many more. When found, GitHub raises a warning, and for some providers it immediately notifies the secret owner to revoke it. Enable it at Settings → Code security and analysis → Secret scanning.

Dependabot Alerts — monitors the dependencies used by the repository and warns when there is a CVE (known vulnerability). Dependabot can even create fix Pull Requests automatically through Dependabot security updates.

Dependabot: check npm daily
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 5

This workflow lives at .github/dependabot.yml. With this simple configuration, Dependabot checks dependencies every day and opens PRs for the latest versions.

Branch Protection Rules

Branch Protection Rules are policies that require certain conditions before a commit can be merged into a branch — most commonly applied to main. Configure them via Settings → Branches → Add branch protection rule, then enter a branch name such as main.

The key options you must know:

  • Require a pull request before merging — all changes must go through a PR and require an approved review.
  • Require status checks to pass — CI/CD (e.g. lint and test) must be green before merging.
  • Require signed commits — commits must be signed with a GPG or SSH key to verify the author's identity.

With this combination, no code enters main without a PR, without green CI, and without verified identity — a quality and security gateway in one.

CI workflow required as a status check
name: CI
on: [push, pull_request]
jobs:
  lint-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: bun install --frozen-lockfile
      - run: bun run lint
      - run: bun run test

Signed commits can be verified from the terminal:

Verifying commit signatures
git verify-commit HEAD
git log --show-signature -3

Note

Branch protection is applied per branch with name patterns, so you can create different rules for main (strict), staging (moderate), and feature/* (relaxed). Start with the most important one: main.

Emergency Steps if a Secret Was Already Committed

Stay calm and follow this order. The most important thing is not deleting history — it is revoking that secret's access as quickly as possible.

Warning

Do not try to "clean up" a secret only with git reset --hard followed by a force push. git reset --hard destroys changes and does not remove the secret from already-pushed history — the secret stays in old commits, in your teammates' clones, and in GitHub's cache. Rotate the secret first, then clean up the history.

The emergency response sequence:

  1. Rotate or revoke the secret at its provider (e.g. regenerate the API key in AWS, reset the database password). This is the only step that truly neutralizes the leak.
  2. Remove the secret from the file and add that file to .gitignore.
  3. Clean the history with git filter-repo (the safer, faster successor to filter-branch) or BFG.
  4. Push again with team coordination — this falls under force push, which requires permission.
  5. Ask everyone who has cloned the repository to do a hard reset to the latest commit.
Removing an env file from all history
git filter-repo --invert-paths --path .env.local
git remote add origin <URL-repository>
git push --force origin main

Note: git filter-repo removes the remote configuration — that is why the remote is added again afterward.

Tip

Secret Scanning will flag a secret that was ever detected even after it is removed from the file. After rotating and cleaning the history, make sure the secret status at Security → Secret scanning has been revoked — only revocation truly closes the risk.

Closing

This episode closes the biggest security gaps of a repository: enforcing rules through Branch Protection Rules with required PRs, status checks, and signed commits; understanding the danger of committed API keys, private keys, and database credentials; preventing leaks with .gitignore; making use of GitHub Secret Scanning and Dependabot Alerts; and handling incidents by rotating the secret before cleaning the history.

The points to take with you:

  • Branch protection on main requires PRs, green status checks, and signed commits.
  • Pushed secrets stay permanently in history — prevention is better than cleanup.
  • Secret Scanning and Dependabot Alerts are GitHub's automated defense layers.
  • When a secret leaks: rotate first, then clean the history with git filter-repo.
  • git reset --hard destroys changes and does not remove the secret from the remote.

Security fixes the future; the next episode fixes the past. In episode 14 we cover Time Travel & Undoing Changesgit restore, git revert, and git reset, and when each is safe to use. See you in episode 14!

Learn Git - Repository Security & Branch Protection Rules | Learn Git & GitHub