Skip to main content
RunBook Academy

Git, CI/CD & GitOpsCII · Large Repository PerformanceBoundaries

Binaries and large files — what does not belong in Git

Intermediate⏱ ~18 mingit

What you'll learn

  • Identify the four categories of files that do not belong in Git
  • Detect large blobs with `git rev-list` and `.gitattributes`
  • Recognise the cost of storing compiled output next to its source
  • Route large assets to the correct external store

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

Git is a delta-compressing content store. Text files revise in small deltas; the store earns its keep. The moment a 50 MB compiled binary lands in the tree, the store stops being delta: the binary and its predecessor share no bytes, the delta is the full file, and each revision costs the full 50 MB.

The four categories

  • Compiled output. .o, .jar, .exe, .bin. Duplication of state.
  • Image and media. .png, .mp4, .pdf. Pipeline output or tolerate LFS.
  • Datasets and weights. .parquet, .pt, .onnx. Model registry.
  • Backups, archives. .sql.gz, .tar. Live state; bandwidth, not safety.
git rev-list --objects --all | \
    git cat-file --batch-check='%(objecttype) %(objectsize) %(rest)' | \
    awk '/^blob/' | sort -k2 -nr | head -20

Ranks blobs by size. git-sizer reports the same grouped by extension.

Why binary content is irreversible

A 200 MB .parquet committed in 2022 cannot be removed without rewriting every commit that referenced it. Tags, signed signatures, and CI runs point at different hashes; audit trail breaks for every consumer. A .parquet that never lands costs nothing; one that lands later costs a forced rewrite that breaks pinned systems.

Pre-commit enforcement and routing

A .gitignore is a declaration; a pre-commit hook is the enforcement. check-added-large-files refuses any staged file above the threshold (512 KB sensible; 100 KB if LFS).

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: check-added-large-files
        args: ['--maxkb=512']

Replacement stores: compiled -> artifact; media -> object store; weights -> MLflow; backups -> managed backup. Repository stores a version reference, never the bytes.

Production discipline

  1. Set a pre-commit size threshold (512 KB default, 100 KB if LFS).
  2. Apply .gitignore before the first commit.
  3. Route assets to their correct store.
  4. Treat any large file as deliberate.

Cross-course references

  • Linux for Production Sysadmins Part XXVI: build output in /var/cache.
  • Terraform for Production Sysadmins Part IX: state in a backend.

Quiz

Knowledge check · 4 questions

  1. Q1. An engineer commits a 320 MB parquet dataset to the Terraform repo so it can be inspected during plan review. Which problem is most directly created?

  2. Q2. A `.gitignore` rule added to a repository years after the offending directory was first committed removes the directory from the next clone.

  3. Q3. Name the four categories of files that do not belong in Git, and the pre-commit hook that rejects files above a size threshold.

  4. Q4. Diagnose why a Terraform repository has ballooned to 14 GB, and recommend routing.

    Team G: 14 GB repo. Largest blobs: 1.2 GB SQLite dump; 600 MB scikit-learn model; 400 MB provider plugin. Clone 35 min.

Passing score: 75%. Answers are checked in this browser.