DEV Community

Shyam
Shyam

Posted on

git blame lied to me: the 2020 bug fix hiding behind a 2023 refactor

This line is in Flask's app.py:

self_ref = weakref.ref(self)
Enter fullscreen mode Exit fullscreen mode

Looks over-engineered. Why not just self?

git blame says 2023

$ git blame -w -M -C -C -C -L355,355 src/flask/app.py
0ec7f713 (pgjones 2023-06-11)  self_ref = weakref.ref(self)
Enter fullscreen mode Exit fullscreen mode

"Split the App and Blueprint into Sansio and IO parts." That commit only moved code. Blame tells you who last touched a line, not why it exists.

The real reason is from 2020

$ git log -S"weakref.ref(self)" --oneline
0ec7f713 Split the App and Blueprint into Sansio and IO parts
8efea0cc Break reference cycle created by default in Flask instances.
Enter fullscreen mode Exit fullscreen mode

The weakref stops a memory leak (#3761). "Simplify" it and the leak is back. You'd only find this if you already suspected a story.

So I built Blot

Blot is a pre-commit hook that has read your git history. It warns when a commit:

  • removes a fix: edits a line a bug fix added
  • re-adds a bug: brings back a line a fix removed
  • forgets a related file: changes A but not B, when they always change together

demo

Or ask about any line. It skips commits that only moved code:

$ blot why src/flask/app.py:355
  explained by  8efea0cc  2020-10-03  Break reference cycle ...  [bug fix]
  traced past   0ec7f713  2023-06-11  Split the App and Blueprint ...  [refactor]
Enter fullscreen mode Exit fullscreen mode

Local, no AI, no account. Warns, never blocks.

Staying quiet was the hard part

My first version gave Django 26 warnings per 10 commits. So I replayed the last 500 commits of 5 repos, read every warning, and turned each noise pattern into a rule.

Repo Before After
Flask 1.96 0.10
Express 1.00 0.18
Django 26.30 1.29

The replays also found real moments, like Express reverting the CVE-2024-51999 security patch. Blot flagged it.

Try it

pip install blot-git
blot index
blot install-hook
Enter fullscreen mode Exit fullscreen mode

GitHub logo Sym-jay / Blot

A pre-commit check that has read your project's history. Sora the slime warns when a change removes a fix, re-adds a fixed bug, or forgets a file that always changes too.

Blot

CI PyPI

Sora, the Blot slime, sliding back and forth

A pre-commit check that has read your project's history.

Meet Sora, the slime who remembers every fix.

Don't take down a fence until you know why it was put up.

Blot warns you before you commit when your change:

  • removes a fix: deletes or edits code that was added to fix a bug
  • re-adds a bug: brings back a line that a bug fix deliberately removed
  • forgets a related file: changes A but not B, when the two almost always change together

It runs locally, needs no account or AI, and stays quiet unless the history gives it a real reason to speak.

Blot catching a real Flask regression: simplifying self_ref = weakref.ref(self) triggers a removed-fix warning that traces past a 2023 refactor to the 2020 reference-cycle fix

A real run on Flask. Plain git blame points to a 2023 commit that only moved this line; Blot traces past it to the 2020 fix that explains it. (Regenerate with python assets/demo/make_demo.py.)

Status: pre-alpha. Milestones M1 and M2 are…





Pre-alpha. If it cries wolf on your repo, open an issue; that's exactly the feedback I need.

Built with help from Claude (of course, phew); every number here is from a real run.

Top comments (0)