This website uses cookies

Read our Privacy policy and Terms of use for more information.

Everyone who shared the GitClear numbers this month read them the same way: AI writes sloppy code. Refactoring line-moves down 70% since 2022, duplicated blocks up 81%, copy/paste now roughly five times more common than refactoring. The obvious conclusion is that the model has bad taste, that it pastes where a careful engineer would consolidate, and that the fix is a better model or a stricter linter.

That conclusion is comfortable and wrong. Refactoring is not a code-quality behavior that a well-behaved author performs and a lazy one skips. It is the visible byproduct of a specific human act: reading the code that already exists before you add to it. You do not extract a shared function until you have noticed that two call sites do the same thing, and you only notice that by reading both. When the refactoring rate falls off a cliff, the thing that actually fell is the reading. The duplication going up and the refactoring going down are not two findings. They are one finding, measured from two sides.

The numbers are worse than "AI is messy"

GitClear's 2026 report tracks eight signals across 623 million changes from 2023 to 2026, the window in which AI authorship went from a novelty to a quarter of all commits. The signals split cleanly into two groups, and the split is the whole story.

The "reuse" signals are the moves you make when you understand the surrounding system. Refactoring line-moves fell from 21% of changed lines in 2022 to 3.8% year-to-date in 2026. Function connectivity, how often new code calls into existing methods rather than standing alone, dropped 35% since 2023, from 343 calls per thousand changed lines to 223. Long-term legacy maintenance, the share of changes that touch code last modified more than a year ago, fell 74%, from 1.7% to 0.46%.

The "risk" signals are what fills the vacuum. Within-commit copy/paste climbed from 9.4% in 2022 to 15.7% in the first half of 2026. Duplicated blocks, meaning five or more consecutive repeated lines, rose 81% to a record 73 per million changed lines. In 2022, GitClear's earlier Coding on Copilot data showed engineers preferring to refactor over paste by about two to one. Today they paste over refactor by about five to one. That is not a small drift. That is a full inversion of the default.

Read as eight separate problems, this looks like eight things to fix. Read correctly, it is one thing happening eight times. Every one of those signals, reuse and risk alike, is downstream of whether a human read the code before changing it.

You can't extract what you never read

Consider the smallest possible refactor. Two places in the codebase parse a duration string the same way:

# billing/invoice.py
def total_hours(entries):
    seconds = 0
    for e in entries:
        h, m, s = e["dur"].split(":")
        seconds += int(h) * 3600 + int(m) * 60 + int(s)
    return seconds / 3600
# reports/timesheet.py
def worked_hours(rows):
    seconds = 0
    for r in rows:
        h, m, s = r["duration"].split(":")
        seconds += int(h) * 3600 + int(m) * 60 + int(s)
    return seconds / 3600

The refactor is trivial once you see it: pull the parse into a shared hms_to_seconds helper and call it from both. But seeing it is the entire job. The extraction is the last, cheap step of a process whose expensive step is knowing that reports/timesheet.py exists and does the same arithmetic under a different variable name. That knowledge does not come from taste. It comes from having read the file.

Now watch what a default AI workflow does with the same task. You are in billing/invoice.py and you ask for a function to total hours. The model produces a correct, self-contained, locally complete answer. It has no reason to open reports/timesheet.py, and in most workflows it was never handed it. The output passes its test and closes the ticket. The duplicate is born not because the model is careless but because it is not standing in the place where the duplicate becomes visible. Refactoring gets discovered by the person doing the reading, and in this loop nobody did the reading.

This is why the collapse is structural rather than stylistic. A messy author still reads the neighborhood and chooses to paste anyway; you can coach that person. What the GitClear panel describes is a workflow where the reading step has been removed from the critical path entirely. For most of software history that step was not optional, because you could not change code you did not first understand. AI decoupled the two. You can now ship a working change to code you never read, and the refactor that used to ride along for free rides along no longer.

The decay lives in the negative space

Here is the part that makes this hard to catch. Everything AI removed from the loop was invisible to begin with. Refactoring, reuse, and legacy maintenance are not features. They are the absence of future pain. A dashboard can show you the pull request that shipped. It cannot show you the function that was reinvented instead of reused, or the duplicate that was not consolidated, or the year-old module nobody returned to. GitClear can only see these because it measures the shape of change over time, and the shape is contracting toward isolated, self-contained, never-revisited code. The company's own phrase for the result is "perpetual V1": the codebase grows outward with new first drafts while its older strata freeze and calcify.

Addy Osmani gave the human side of this a name in March: comprehension debt, the growing gap between how much code exists in your system and how much of it any human genuinely understands. His framing and GitClear's data are the same phenomenon seen from opposite ends. Comprehension debt is the cause. The GitClear signals are its structural shadow, the marks left in the diff history when understanding leaves the loop. The 81% duplication rise is not the model failing at deduplication. It is the missing engineer who used to say, "wait, we already have this."

Osmani points at the mechanism that keeps it invisible: the review that used to force comprehension no longer does. When a human wrote the code, reading their pull request was a slow, productive bottleneck. It surfaced hidden assumptions and spread knowledge of what the system actually does. AI inverts the economics. A junior engineer can now generate code faster than a senior can critically audit it, so the review that was a quality gate becomes a throughput problem, and the honest answer to "do you understand this diff" quietly shifts from yes to it passed the tests.

It compounds, and your metrics can't see it

Each un-refactored duplicate raises the comprehension cost of the next change to that area, which makes the next engineer even less likely to read it, which produces another duplicate. The loop feeds itself. Margaret-Anne Storey documented a student team that hit the wall in week seven: they could no longer make simple changes without breaking something unexpected, not because the code was messy, but because nobody could explain why the design decisions had been made. The theory of the system had evaporated. That is comprehension debt reaching its due date on a fast-forward timeline.

The evidence that this degrades the engineers themselves, not just the repo, is now direct. Anthropic's randomized trial on skill formation put 52 mostly-junior engineers to work learning Python's Trio library, a technology none of them knew. Half used an AI assistant. The AI group finished in roughly the same time, with productivity gains that did not reach statistical significance, and then scored 17% lower on a comprehension quiz afterward, 50% against 67%. The largest drop was in debugging, the skill that most requires holding the system in your head. The split inside the AI group is the sharp part: engineers who used AI to ask conceptual questions scored above 65%, while those who delegated the code generation scored below 40%. The tool does not remove comprehension. Delegating past it does.

And none of this shows up where teams look. Velocity is up. DORA metrics hold. Pull request counts rise. Coverage stays green. The incentive structure optimizes correctly for exactly what it measures, and what it measures no longer includes whether anyone understands the code. You cannot put "the read that didn't happen" on a burndown chart.

Yes, but the metric is a proxy, and the tools are improving

Two honest objections. The first is that GitClear's numbers are proxies and the causal story is contested. "Moved lines" undercounts refactors performed through IDE tooling or inline by the AI itself, so some real consolidation is invisible to the metric. Repo composition also shifted over the window; teams shipping more greenfield features will naturally refactor less regardless of AI. Both are fair, and they mean the exact coefficients, the 70% and the 81%, should be held loosely. What they do not touch is the direction, which shows up independently across eight signals that would not all move together by accident, and which lines up with the Anthropic trial's measured comprehension drop. When a proxy and a controlled experiment point the same way, the mechanism survives even if the numbers are soft.

The second objection is that agentic refactoring is getting genuinely good. Point an agent at a duplicated block and it will extract the helper faster than you could. True, and it changes less than it seems. The agent will refactor what you tell it to, and you only know what to tell it if you have read the code well enough to find the duplication in the first place. The expensive half was never the extraction. It was the noticing. AI made the cheap half free and left the expensive half exactly where it was, which is the same asymmetry that produced the problem, now sold back as the solution.

What to do Monday

Stop treating refactoring as a cleanup sprint you schedule when there is slack, and start reading it as a receipt. If your team shipped a week of AI-assisted changes and the refactored fraction is near zero, that is not a tidy codebase. It is a codebase nobody read. The refactoring rate is the cheapest available proxy for whether comprehension is still in your loop, and it costs nothing to watch.

Change one question in review. Not "does this pass," which the tests already answer, but "what existing code did you consider reusing here, and why didn't you?" If the honest answer is "I didn't look", you have found the actual defect, and it is not in the diff. Make that a required note on any non-trivial change and you convert an invisible omission into a reviewable artifact.

Then instrument the negative space directly. Track duplication and function connectivity over time, not just velocity, and put a tripwire on newly introduced duplicate blocks the way you would on a failing test. You will not catch everything, but you will at least be measuring the dimension that is actually decaying instead of the three that always look fine.

The one line to keep: AI made writing code cheap and left understanding it exactly as expensive as it always was. Every workflow that treats the cheap half as the whole job is quietly deferring the expensive half, and that bill compounds. Budget for the reading, or pay for it later at interest.

Sources

Keep Reading