Free — no signup required

Organizing Your Git Repository: Directory Structure

2 min read

Designing for Multiple Environments

How do you manage different environments (Dev, Staging, Prod) in Git? Three common approaches exist:

  1. Branch-per-environment: dev branch, staging branch, main branch. Simple to understand, but merging between branches is error-prone and Git history becomes hard to follow.
  2. Repo-per-environment: Separate Git repos for each environment. Clean isolation, but duplicates configuration and makes cross-environment changes tedious.
  3. Directory-per-environment (recommended): A single repo with a directory structure that separates shared base configuration from environment-specific overrides, using Kustomize.

The directory-per-environment pattern is the most widely adopted because it keeps all configuration in one place while making environment differences explicit and reviewable.

Kustomize: Base and Overlays

Kustomize is a Kubernetes-native configuration management tool (built into kubectl). It works by defining a base — the common configuration shared across all environments — and overlays that patch the base for each specific environment.

gitops-repo/
├── apps/
│   └── payment-api/
│       ├── base/                         # Shared across all environments
│       │   ├── deployment.yaml           # image, ports, env vars (non-secret)
│       │   ├── service.yaml
│       │   └── kustomization.yaml        # Lists resources in base
│       └── overlays/
│           ├── dev/
│           │   ├── kustomization.yaml    # References base, applies dev patches
│           │   └── patch-replicas.yaml  # replicas: 1
│           ├── staging/
│           │   ├── kustomization.yaml
│           │   └── patch-replicas.yaml  # replicas: 2
│           └── prod/
│               ├── kustomization.yaml
│               └── patch-replicas.yaml  # replicas: 5
└── clusters/
    ├── dev-cluster/
    │   └── payment-api.yaml             # ArgoCD Application → overlays/dev
    ├── staging-cluster/
    │   └── payment-api.yaml             # ArgoCD Application → overlays/staging
    └── prod-cluster/
        └── payment-api.yaml             # ArgoCD Application → overlays/prod

The clusters/ directory contains the ArgoCD Application or Flux Kustomization CRDs that tell each cluster's GitOps agent which path to watch. The dev cluster's agent watches overlays/dev; the prod cluster's agent watches overlays/prod.

Promoting changes from dev to prod is a Pull Request that updates the prod overlay — no special tooling, no pipeline magic. The PR is the promotion mechanism, and Git history is the promotion audit trail.

The base's kustomization.yaml simply lists the resources that make up the shared configuration (the Deployment and Service). The prod overlay's kustomization.yaml references that base directory, layers on its replica patch, and uses an images transformer to pin the container to a specific tagged version rather than inheriting whatever the base points at — prod runs a fixed release, not a floating tag.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free