Deleted per 100 added: mature projects delete, young ones mostly add

Raghav Chamadiya7 min read

code churn · lines deleted · git history analysis · deleting code · codebase growth · refactoring

On this page

Over 15 years, requests has added 161,376 lines and deleted 132,211. That is 82 lines deleted for every 100 added. Almost everything it has ever written has been rewritten or removed, and what is left is about 29,000 lines.

I looked at the same ratio for every popular repo where we have the complete git history. The older the project, the more it deletes.

The ratio by age

We have full history for 33 public repos with 500+ stars and a health score. Grouped by the year of their first commit:

Project startedReposMedian lines deleted per 100 added
before 2015969.6
2015 to 2019863.3
2020 to 2024652.8
2025 or 20261042.5

Scroll the table sideways to see every column.

The groups are small, so the trend matters more than the decimals. Each later group deletes less than the one before.

Some of the mature projects, for reference:

RepoStartedAddedDeletedPer 100 added
psf/requests2011161,376132,21181.9
keycloak/keycloak20139,679,4227,833,19480.9
cakephp/cakephp20051,991,4111,602,01280.4
gohugoio/hugo20131,093,550761,37669.6
temporalio/temporal20163,431,3962,320,07867.6
react/react20133,475,8642,324,61866.9
bevyengine/bevy20192,047,2901,289,46963.0
apache/airflow20145,718,1733,211,67856.2
microsoft/PowerToys2013 (history inherited from the 2013 repo)3,174,1151,681,89253.0
fastapi/fastapi2018808,997414,41851.2

Scroll the table sideways to see every column.

In absolute terms Keycloak stands out: it has written almost ten million lines and deleted almost eight million of them.

Where deletions come from

These kinds of change produce deleted lines in a mature project:

  • Replacing your own first attempt. The first version of anything is written before you know the real requirements, and once you do, the second version replaces the first and the first one's lines show up as deletions.
  • Dropping old platforms. Every Python version, browser or OS a project stops supporting takes compatibility code with it. requests' changelog records it dropping Python 2.6, 2.7, 3.4, 3.5, 3.6, 3.7, 3.8 and 3.9 over the years, and each step removes branches nobody needs anymore.
  • Moving code out. When a project splits into packages or hands integrations to their own repos, the code leaves as deletions. LangChain, which started in 2022, has the highest ratio in the whole set at 85.6 per 100. It has moved many integrations into separate packages, and some, like langchain-aws and langchain-google, into separate repos. I haven't measured how much of its ratio that explains, but code that leaves a repo counts as deleted.
  • Formatting and tooling changes. A switch to a new formatter or a big rename touches a lot of lines at once and counts as both an add and a delete, which inflates both sides and pushes the ratio toward 100. It's noise, and any project that has ever reformatted its code carries some of it.

The first three need old code to act on, so I'd expect them to be rare in a project's first year.

Young projects

The 2025 to 2026 group deletes 42 lines per 100 added, which is still a lot of deleting. Our own repo, repowise, started in March 2026 and sits at 21.6: we've added about 1.5 million lines and deleted about 330,000. Most of what we've built is still the first version of itself.

That is normal for a young project, and I think it's also the number to keep an eye on. Two things push it down at the moment:

  1. Growth. A new project is adding features faster than it is finding out which ones were built wrong.
  2. Cheaper code. When a coding agent can write a new module in minutes, writing a fresh one is often easier than finding and changing the old one. GitClear's research on 211 million changed lines found that "moved" code (a sign of refactoring) fell from about 25% of changed lines in 2021 to under 10% in 2024, while copy-pasted code rose. That suggests some lines that could have replaced old ones are being added next to them instead.

I can't separate those two with this data. The ratio can't tell you whether a project is growing healthily or piling up duplicates. What it can do is give you a question to ask: if your project is two or three years old and still deletes under 30 lines per 100, is that because everything you built was right the first time?

Checking your own

You don't need any tool for this. From the root of any repo:

bash
git log --shortstat --pretty=tformat: | perl -ne '$a+=$1 if /(\d+) insertion/; $d+=$1 if /(\d+) deletion/; END { printf "added %d, deleted %d, %.1f per 100\n", $a, $d, 100*$d/$a }'

That counts every non-merge commit reachable from your current branch, the same way we do. The stats page on repowise shows it for any public GitHub repo, alongside the busiest day, the longest streak and the code's half-life.

Limits of this number

  • The groups are small: 33 repos split four ways. The trend is consistent, but any one group could move a few points if we added ten more repos.
  • Vendored and generated code counts like everything else. A project that commits a lockfile or a generated client will show large adds and deletes that have nothing to do with design.
  • There are exceptions both ways. Chatwoot (2019) sits at 31.3 and LangChain (2022) at 85.6. Age sets the trend, and single projects vary a lot around it.
  • Survivorship affects the old groups. The old projects in this sample are the ones that stayed popular for ten years or more. Projects that started in 2013 and stalled aren't here, so the older groups may look tidier than old projects in general.
  • Some young repos are only weeks old. The 2025 to 2026 group includes repos whose first commit was a few weeks before we indexed them, and our own repo is one of its 10 members.
  • History cuts matter. Only repos where we indexed the full history are included. Many famous projects were cloned with a 500 or 1,000 commit limit, and their ratio would describe only their recent past.

How we measured

For each repo we sum git log --shortstat over every non-merge commit reachable from the default branch, which gives total lines added and deleted. We kept public repos in our index with 500+ GitHub stars, a health score, and a full clone (no commit limit): 33 repos. "Started" is the year of the first commit. Data checked on 6 October 2026.