skip to content

Should generated source be committed with hand-written code, or re-derived on every build — how do you decide?

level: principalimportance: should knowfreq 34%

answer

  1. drift against dependency
  2. who must build without the generator?
  3. bootstrapping breaks the cycle
  4. re-derive and compare in the build
  5. the check needs byte-stable emission

basics

~20 s

Decide by who must be able to build and read without the generator. Re-deriving removes drift but demands the toolchain everywhere; committing buys readability, offline consumption and bootstrapping at the price of diff noise and drift, which a re-derive-and-compare check contains.

solid answer

~50 s

It is a trade between **drift** and **dependency**. Re-deriving on every build makes drift impossible — there is one source of truth and the output is a function of it — but every consumer, every environment and every editor now needs the generator, and build time carries it. Committing the output means anyone can build, read and navigate without the toolchain, external consumers get something usable, and a generator upgrade shows its effect in a reviewable diff; the price is noise in diffs and history, merge conflicts, repository growth, and the real risk that someone changes an input and forgets to re-derive. The workable middle is to commit only where a consumer genuinely cannot run the generator, and to enforce a build check that re-derives and fails if the result differs from what is committed — which requires byte-stable emission to work at all.

go deeper

for a junior

Recall that machine-written files may or may not be kept in the repository, that it is a deliberate team decision either way, and that you do not edit them in either case.

for a middle

Explain both sides concretely: what a consumer without the generator cannot do, and what drift looks like when someone changes an input and forgets to re-derive.

for a senior

Show the guard rather than the opinion — a build step that re-derives and compares, and the byte-stable emission it depends on to be usable at all.

for a principal

Own it as a standard across repositories: where output lives, whether it is committed, what the drift check is, and who is accountable for a defect found in emitted code.

This is one of the few genuinely open questions in output hygiene: everything else has a right answer, and this one has a trade. Decide it deliberately, at the level of a platform standard, because both answers are defensible and the failure mode is drifting between them. ## What each answer buys | | Re-derive every build | Commit the output | |---|---|---| | Drift | Impossible; output is a function of the inputs | Real, and silent until something breaks | | Toolchain | Every consumer and environment needs the generator | Only the team that regenerates needs it | | Review | Only the input change is reviewable | The effect of a generator upgrade is visible as a diff | | History | Clean; records only what people wrote | Noisy, but records what actually compiled at each revision | | Build time | Emission on every clean build | Paid only when someone regenerates | | Debugging | Output exists only if the build kept it | Emitted source is always available to read | | Repository | Small | Grows with every emitted line, forever | ## The questions that actually decide it 1. **Who has to build this without the generator?** External consumers, a constrained environment, an editor doing analysis before any build has run — each of these is a reason to commit. If the only consumer is your own build, re-deriving is cleaner. 2. **Is there a bootstrapping cycle?** If the generator is needed to build something the generator itself depends on, committing an output breaks the cycle. This is rare and decisive when present. 3. **Is emission byte-stable?** If it is not, committing guarantees a rebuild diff on every run and the drift check cannot exist. Fix stability first or do not commit. 4. **How costly is emission?** Emission measured in seconds is noise; emission that dominates a clean build changes the calculus for everyone who only wanted to read the code. 5. **Will anyone actually review the emitted diff?** If the honest answer is no, committing buys history, not scrutiny — and be clear about which of the two you are paying for. ## The middle path, and its precondition Most mature answers land in the same place: **re-derive by default, commit only where a consumer cannot run the generator, and guard the committed copy with a check.** The check re-derives during the build and fails when the result differs from what is committed. It converts drift from a silent condition into a build failure, and it turns the committed copy into a cache rather than a second source of truth. The check has one precondition, and it is absolute: emission must be **byte-stable** — no timestamps, no host-dependent paths, an order the generator imposes rather than inherits. Without that, the comparison fails on every run, somebody disables it, and the team is left with committed output nobody is checking, which is the worst of the three states. ## Failure modes to name - **Drift.** Someone edits an input, does not re-derive, and the committed output stays behind. The build is green because the stale output still compiles. Only the check catches it. - **Hand edits.** Committed output is a file in the tree like any other, so it attracts edits; without a derived marker and a review rule, one lands and is reverted by the next regeneration. - **Rubber-stamped diffs.** A large emitted diff arrives with a small input change, nobody reads it, and a template regression ships inside it. - **Conflicts.** Two branches regenerate, and reordered or renumbered output conflicts although neither changed behaviour. Byte-stable emission with an input-derived order reduces this to the cases that really did both change. ## How to state the decision Write it down as a standard, not per repository: where emitted output lives, whether it is committed, what marker it carries, what the drift check is, and who owns a defect found in it. The decision is cheap; the cost is a fleet that answers it three different ways, so that no reviewer can tell from looking at a file whether the diff in front of them needed reading.

  • What single guard makes committed output safe enough to live with?
    A build step that re-derives the output from current inputs and fails when it differs from what is committed. It turns drift into a build failure instead of a silent inconsistency, and it demotes the committed copy from a second source of truth to a cache. It only works if emission is byte-stable.
  • A generator upgrade rewrites thousands of committed lines. How should that land?
    As its own change, containing nothing but the toolchain bump and the regeneration it caused, so the diff means one thing. Mixing it into a feature change hides both. Reviewers should read the generator and template change and sample the output, not attempt every emitted line.
  • Does committing the output remove the need for a derived-file marker?
    No — it increases it. A committed emitted file looks exactly like hand-written code in the tree and in a diff, so the marker and a dedicated directory are the only things telling a reader, a style check and a reviewer that nobody wrote it and that editing it is pointless.
  • When is re-deriving on every build clearly the wrong call?
    When a consumer cannot run the generator at all — an external team on a different toolchain, a constrained environment, or a bootstrapping cycle where the generator depends on something the generator produces. Also when emission dominates build time for people who only need to read or analyse the code.

saying these in an interview costs you the question

  • Says committing output removes the possibility of drift
  • Commits emitted files without any check that they match the inputs
  • Assumes a large emitted diff will be reviewed line by line
  • Ignores consumers who cannot run the generator at all
  • Commits output from a generator whose emission is not byte-stable
  • Answers it per repository instead of as one standard