Lesson 07 of 8 · Level 3 — Git for platforms
Repositories for infrastructure and GitOps
Repositories that hold infrastructure and GitOps configuration need extra care: how to split them, route reviews with CODEOWNERS, catch problems before commit with pre-commit hooks, keep secrets out with scanning, sign commits, and clean up properly when a secret slips through.
Mono repo or many repos?
| Monorepo (one repo for many services or all infrastructure) | Polyrepo (one repo per service/component) | |
|---|---|---|
| Strengths | Atomic changes across components, one set of tooling, easy search | Clear ownership, independent access control, small and fast |
| Costs | Needs path-based CI, CODEOWNERS and good tooling as it grows | Cross-repo changes need coordination; tooling duplicated |
For platforms, a common split: application source in per-service repositories; infrastructure (Terraform) in one or a few repositories by layer or team; GitOps configuration (what runs where) in a dedicated config repository. "GitOps Principles & Practice", lesson 02, goes deeper.
A shared family calendar (one repo) makes it easy to see everything at once, but everyone needs to agree on the rules. Separate diaries (many repos) give privacy and freedom, but planning a family holiday means comparing them all.
CODEOWNERS: the right reviewers, automatically
# .github/CODEOWNERS (GitLab: CODEOWNERS with the same syntax, Gitea: similar)
* @acme/platform-team
/terraform/network/ @acme/network-team
/environments/prod/ @acme/platform-leads
/apps/payments/ @acme/payments-team
With branch protection requiring code-owner approval, a change to environments/prod/ can't merge without a platform lead. The file itself should be owned by the platform team.
pre-commit: catch it before it's committed
# .pre-commit-config.yaml (pin rev to versions you tested)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
args: [--allow-multiple-documents]
- id: check-merge-conflict
- id: detect-private-key
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.0
hooks:
- id: gitleaks
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.99.0
hooks:
- id: terraform_fmt
- id: terraform_validate
$ pre-commit install # hooks now run on every git commit in this clone
$ pre-commit run --all-files # run everything once
Run the same checks in CI (hooks can be skipped with --no-verify; CI can't).
Keep secrets out of Git
- Never commit secrets, even to private repositories: private repos get cloned, forked, mirrored and backed up.
- Use a secret store (Vault, AWS Secrets Manager) or encrypted-in-Git formats built for it (SOPS, Sealed Secrets: see "GitOps Principles & Practice", lesson 04).
- Scan with gitleaks in pre-commit and CI; enable your Git server's secret scanning and push protection where available.
When a secret leaks anyway:
- Rotate/revoke it now. This is the only step that actually removes the risk.
- Check where it could have been used (cloud audit logs, access logs).
- Remove it from history if required:
git filter-repo --path <file> --invert-paths(or--replace-text), force-push, and ask everyone to re-clone. Coordinate this; it rewrites every later commit. - Add the pattern to the scanner so it can't happen the same way again.
Signed commits
Signing proves a commit came from the holder of a key, which matters for repositories that control production (GitOps configuration, Terraform):
$ git config --global gpg.format ssh
$ git config --global user.signingkey ~/.ssh/id_ed25519.pub
$ git config --global commit.gpgsign true
$ git config --global tag.gpgsign true
Upload the same key as a signing key on the Git server; commits then show as verified, and branch protection can require signatures.
Try it: guard a repository
- Add the
.pre-commit-config.yamlabove to a test repo (adjust versions), runpre-commit installandpre-commit run --all-files. - Try committing a file containing a fake AWS key pattern; watch gitleaks block it.
- Add a CODEOWNERS file and require code-owner review on
main; open a PR touching an owned path. - Turn on SSH commit signing and check
git log --show-signature -1.
Recap
- Split app source, infrastructure and GitOps config sensibly; monorepo vs polyrepo is about ownership and tooling.
- CODEOWNERS + branch protection = the right reviewers, enforced.
- pre-commit locally and the same checks in CI; gitleaks for secrets.
- Leaked secret: rotate first, then clean history with
git filter-repo. - Sign commits for repositories that change production.
This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.