Twelve gigabytes. That is what greeted me the first time I cloned this repository. My first thought was that something had broken on my machine — a bad mount, a runaway cache, a corrupted pack. It had not. The repo really was that big, and by the end of the week I had learned more than I wanted to about how to shrink a Git repo and remove passwords from its history without losing a single line of real work.

Here is how the rescue went, and the guardrails I left behind so it never grows back.

The archaeology

Before you clean anything, you have to know what you are cleaning. A repo does not reach twelve gigabytes by accident — every megabyte has a story, usually a bad one.

I walked the object database with git rev-list --objects --all piped through git cat-file to sort blobs by size. The treasure map wrote itself. Committed straight into history, I found:

  • JARs and ZIPs — build artifacts that should never have been near Git
  • Docker images, committed as tarballs, because someone needed them "just once"
  • Thousands of stale branches, most of them dead for years
  • And the part that stopped me cold: real passwords and API keys, sitting in old commits, quietly waiting for someone curious enough to run git log -p

That last one reframes everything. This was not a bloated repo. It was a security incident that had not been noticed yet.

Rotate first, then scrub

Everyone reaches for BFG Repo Cleaner or git filter-repo to strip secrets from history. That is the right tool — but the order matters more than the tool.

Rewriting history does not un-leak a secret. The moment a password lands on a remote that other people, CI runners, and forks have pulled, you have to assume it is compromised. So the sequence is non-negotiable:

  1. Rotate every exposed credential first — new keys, new passwords, old ones revoked
  2. Then scrub the old values from every commit
  3. Then force-push and have everyone re-clone

Do it in the wrong order and you have spent a weekend rewriting history to hide a key that is still valid.

The cleanup

With secrets rotated, the surgery began. BFG Repo Cleaner stripped every binary and every known secret string from the entire history. Large files that still had a reason to exist moved to a proper artifact registry, where binaries belong. Stale branches were archived and deleted in bulk. Then a git gc --aggressive and a repack to actually reclaim the space on disk.

Twelve gigabytes became a lean repo that clones in seconds instead of a coffee break.

While I was in there: the pipeline

A repo this neglected never has a healthy pipeline either. So I restructured the CI while everything was already torn open:

  • Sequential stages split into parallel wherever nothing forced them to be serial
  • Docker layer caching added, so we stopped rebuilding the world on every commit
  • Selective testing, so a change to one module runs that module's tests, not the entire suite

Clone time and build time both dropped from "go make coffee" to "already done".

The guardrails

Here is the part most cleanups skip, and it is the only part that matters long term. Cleanup without guardrails is a temporary fix — the same habits that bloated the repo will refill it within a year. So I built the fence:

  • Pre-commit hooks that reject any file over 5 MB before it ever enters history
  • A branch lifecycle policy that auto-deletes branches 7 days after merge
  • Secret scanning wired directly into the CI pipeline, so a leaked key fails the build instead of living in history
  • Repo size monitoring with alerts, so creep gets caught at 200 MB, not 12 GB

The lesson

Your Git repository is the foundation of your entire delivery pipeline. Everything — CI, deployments, developer onboarding, your security posture — sits on top of it. When it is clean, everything downstream flows. When it is a twelve-gigabyte time capsule of bad decisions, everything downstream drags.

If your clone takes longer than your coffee, your repo is trying to tell you something. Listen to it — then go run a secret scan on it tonight. You may not like what shows up, and that is exactly why you should look.