KiCad has one property that makes it a joy to version-control and that a lot of engineers never take advantage of: its files are plain text. Schematics, boards, and project settings are all human-readable S-expressions. That means Git — the same tool the software world has used for two decades — works beautifully on your PCB projects. You get real history, real diffs, and reproducible releases.

The catch is that KiCad doesn't set this up for you. Do it wrong and you get a repo full of noisy diffs, merge conflicts on cache files, and 200 MB of build artifacts. Do it right — mostly a matter of one good .gitignore and a simple branching habit — and you'll never email board_final_v2.zip again.

Why Git fits KiCad so well

Open a .kicad_sch, .kicad_pcb, or .kicad_pro in a text editor and you'll see structured, line-based text. Because Git diffs line by line, a change to your design shows up as concrete lines added and removed: a new net, a moved footprint, a changed value. Compare that to a binary EDA format where every save is an opaque blob and "what changed?" is unanswerable.

This gives you three things software engineers take for granted:

  • History. Every commit is a restorable snapshot of the whole design. You can check out the exact board you sent to fab six months ago.
  • Diffs. You can see what changed between revisions — useful in review, and invaluable when a board that worked suddenly doesn't.
  • Reproducibility. A tagged commit is a permanent, unambiguous reference to "this exact design," far better than a filename.

A caveat: KiCad's own built-in Git integration has had a rough history — the in-app push in particular has been unreliable. So keep your workflow tool-agnostic. Use plain command-line git, or a GUI client you like (GitHub Desktop, Fork, GitKraken, Sourcetree). The advice below works the same regardless of which you pick.

What to commit and what to ignore

The core rule: commit the source of truth, ignore everything KiCad or a build step can regenerate. Your design files are irreplaceable. Caches, backups, autosave locks, and exported outputs are not.

Commit these Ignore these
*.kicad_pro (project) *.kicad_pcb-bak, *.kicad_sch-bak, *-bak
*.kicad_sch (schematics) fp-info-cache (footprint cache)
*.kicad_pcb (board) ~...lck autosave lock files
*.kicad_sym, *.kicad_mod (project libraries) backups/ (KiCad's auto-archive)
sym-lib-table, fp-lib-table *.bak, *.tmp
*.kicad_dru (design rules), worksheets gerbers/, output/, jlcpcb/ (generated)
README, docs, netlists you hand-maintain 3D render PNGs, exported PDFs

Here's a solid starting .gitignore for a KiCad project:

# KiCad backup files
*-bak
*.kicad_pcb-bak
*.kicad_sch-bak
*.bak

# KiCad auto-archive
backups/

# Locally-regenerated footprint cache
fp-info-cache

# Autosave lock files
*.lck
~*.lck

# Generated manufacturing outputs
gerbers/
output/
fabrication/
jlcpcb/
*.zip

Two ignores people get wrong. First, fp-info-cache — a footprint index KiCad rebuilds locally. Commit it and every teammate fights merge conflicts over a file none of them edited on purpose. Second, generated outputs. It's tempting to commit the Gerbers "so they're saved," but they're derived data; committing them bloats history and guarantees they'll eventually drift out of sync with the design. Generate outputs from a known commit instead — that's the whole point of having the source under version control.

A simple branching model

You don't need a heavy Git-flow ceremony for a hardware project. A lightweight model covers almost everyone:

  • main is always releasable. It reflects your latest known-good design.
  • Branch per change. Starting a new revision or a risky experiment? git checkout -b rev-b-power-rework. Do the work there, commit in logical steps ("re-route 3V3 rail", "add bulk caps on VBUS").
  • Merge back when it's checked. Once the branch passes DRC/ERC and review, merge it into main.
  • Tag releases. When you send a board to fab, tag it: git tag -a rev-b -m "Rev B — sent to JLCPCB 2026-07-10". That tag is now a permanent anchor to the exact files that became real hardware.

The branch-per-revision habit is where Git earns its keep in hardware. You can explore a layout change without endangering the design that's already in production, and if the experiment fails you delete the branch and lose nothing.

Libraries and 3D models

Component libraries are where "text-friendly" gets nuanced. Symbol (.kicad_sym) and footprint (.kicad_mod) files are text and diff cleanly — commit any project-local libraries so the repo is fully self-contained. Someone should be able to clone and open the project without hunting for missing parts. Commit sym-lib-table and fp-lib-table too, but keep them pointing at project-relative paths (KiCad's ${KIPRJMOD} variable) rather than absolute paths on your machine.

3D models are the exception. STEP and WRL files are effectively binary and can be large. A few options, roughly in order of preference:

  • Reference KiCad's bundled 3D models via environment variables and don't commit them at all.
  • For custom models, commit small ones directly; they change rarely, so occasional binary blobs in history are tolerable.
  • For a large shared collection, use a separate library repository or Git LFS so you're not copying hundreds of megabytes into every project.

The principle: keep the repo reproducible without letting it balloon. A clone should give a teammate everything needed to open and build the board, and not much more.

Working as a team

Because two people can't cleanly auto-merge conflicting edits to the same board file, coordination beats cleverness:

  • Divide by file where you can. Multi-sheet schematics let people work on different sheets with far less conflict risk than one shared board file.
  • Avoid simultaneous edits to the same .kicad_pcb. Layout is the hardest thing to merge. A quick "I've got the board this afternoon" in chat prevents most pain.
  • Pull before you start, push when you finish. Small, frequent commits with clear messages keep everyone close to main and shrink any conflict to something reviewable.
  • Review via diffs and DRC. Read the Git diff to see what changed, then open the board and run DRC/ERC to confirm it's sound.

Common pitfalls

  • Committing fp-info-cache or backups/. The number-one source of pointless conflicts. Ignore them from day one.
  • Committing generated Gerbers/BOMs. They drift out of sync with the design and bloat history. Regenerate from source.
  • Absolute library paths. fp-lib-table with a path like /home/you/kicad/... breaks the moment someone else clones. Use ${KIPRJMOD}.
  • Giant, vague commits. "updated stuff" across three sheets and a re-route is impossible to review or revert. Commit in logical chunks.
  • Relying on KiCad's built-in push. It's been flaky. Use command-line git or a dedicated client for anything that matters.

If you've never put a KiCad project under version control, this is the moment to stop the _final_v2 madness — here's the case for why that habit is quietly costing you.

Where GoForFab fits

Version control gives you a clean, reproducible history. The natural next step is turning any commit into a full set of manufacturing outputs — automatically, so your Gerbers, BOM, CPL, and DRC reports always match the exact design you committed. That's exactly what GoForFab does: connect your repo, and every push regenerates the current outputs with kicad-cli. No manual exports, no drift, no artifacts cluttering your history. It's free forever for solo work, so your Git setup and your outputs finally stay in lockstep.