Chesterton's Fence Has a Git Blame
Text
1. The claim
Two claims, and the second is the one that is actually contested.
The weak claim: before deleting a guard clause, a retry, a sleep, a null check or a
special case, spend ten minutes on git log -S and the linked pull request. This is
cheap, it works more often than people expect, and it is not interesting.
The strong claim: the context that would answer the question decays predictably, and the decay is fast enough that the parable’s advice is unavailable for most code older than about three years. What is needed for that case is a procedure, not more diligence.
2. The decay ladder
Every reason for a line of code lives somewhere. The places are ordered by how long they survive, and the ordering is stable across every organisation I have worked in.
survives longest
| inline comment naming the failure
| test asserting the behaviour
| commit message with the reason
| pull request description
| issue tracker entry
| incident channel / chat thread
| the person who wrote it
survives shortest
The bottom four rungs share a property: they are outside the repository. They depend on a vendor account still existing, a chat retention policy, a tracker migration that preserved comments, or a person still answering email. The repository is the only artefact with the same lifetime as the code, which is why the top three rungs are the only ones worth relying on.
Figure 2. The bars rank expected survival rather than measured half-lives. The ranking is the claim; the lengths are only a drawing of it.
3. The obligation this puts on the author
Most writing about Chesterton’s fence addresses the person removing it. The larger gain is on the other side, because it is cheap at the moment of writing and impossible afterwards.
A guard clause should carry its reason at the top of the ladder, in one line, naming the failure rather than the behaviour:
// Rejects zero-length batches. The 2024-11 // ingest incident: an empty batch advanced the // offset without a write, so replay skipped the // window silently. // Test: batch_empty_does_not_advance_offset. if (batch.isEmpty()) return
A test that fails when the guard is removed is better than any comment, because it enforces rather than explains. The comment is for the case where the reason is not expressible as an assertion, which is more common than test-first advice admits: rate limits, ordering assumptions about an external system, and workarounds for defects in software you do not control.
4. The procedure for the decayed case
When the history is genuinely thin, the parable gives no guidance beyond “do not remove it”, which taken literally means codebases only accumulate. The alternative is to convert the unknown into an observation.
| § | Step |
|---|---|
| 1 | Instrument, do not delete. Leave the guard in place and emit a counter with a distinguishing label every time it fires. This is a small, reversible, obviously safe change. |
| 2 | Wait one full business cycle. Not a week. Whatever period contains your month-end close, your quarterly batch, your annual reconciliation. Fences are usually built for the rare path, which is exactly the path a two-week observation misses. |
| 3 | Read the fires. If the counter is non-zero, you now have the reason, expressed as the inputs that reach it, which is better evidence than the original commit message would have been. |
| 4 | If it is zero, remove with the evidence attached. The commit message says the counter ran for the named period at the named volume and never fired. That message is now the top rung of the ladder for whoever revisits this. |
| 5 | Keep the rollback cheap for one more cycle. Removal is a change like any other, and it deserves the same rollback plan as a feature. |
The procedure has a cost, and the cost is the objection.
5. The strongest objection
6. What this paper does not claim
Old code has no special claim on survival, and git blame is not sufficient: Section 2
exists because it usually is not. The ordering in Figure 1 is not a measurement. It is
what I have seen hold everywhere I have looked, which is a weaker thing.
The procedure in Section 4 is not novel either. It is ordinary feature-flag practice pointed at a deletion instead of a release, which is the one place almost nobody points it.
Retirement conditions
This paper MUST be retracted if any of the following is demonstrated.
| § | Condition |
|---|---|
| 1 | A codebase of substantial age where the instrument-then-remove procedure in Section 4 produced no measurable reduction in regressions from cleanup work, compared against a matched period of direct deletion. |
| 2 | Evidence that guard clauses whose recorded reason has decayed are, in aggregate, no more likely to be load-bearing than newly written ones, which would make the caution in this paper an expensive superstition. |
| 3 | Tooling that reliably reconstructs the intent behind a change from the surrounding artefacts, at accuracy high enough that the decay ladder in Section 2 stops mattering. |
Revision history
| Date | Change |
|---|---|
| 2026-08-14 | Text written: the decay ladder, the obligation on the author, the instrument-then-remove procedure, and the objection that this makes deletion too expensive. Retirement conditions added. Confidence unchanged. |
| 2026-02-14 | Listed in Section 5 with a title, a summary and a confidence value. No text. |