Who broke main
Something on main is wrong and you want the commit that did it, not the person. Git has three
answers, each costing a little more: which commit last touched the line, which commit added the word, and which
commit first made a test fail.
The line: git blame
$ git blame api.py ab5768d4 (ana 2026-10-04 12:02:00 +0000 1) line 2 8498150e (ana 2026-10-04 12:03:00 +0000 2) line 3 7742196e (ana 2026-10-04 12:04:00 +0000 3) bug d345f958 (ana 2026-10-04 12:05:00 +0000 4) line 5 56d85dcb (ana 2026-10-04 12:06:00 +0000 5) line 6 $ git log -S bug --oneline 7742196 api: handle the edge case
Each line of the file with the commit that last changed it, its author and the date. The line that reads
bug came from api: handle the edge case. Blame knows only the last touch: a reformat
makes the formatter the author of every line, which -w (ignore whitespace) and
--ignore-rev (ignore that commit) work around. git log -S bug goes further back:
every commit that added or removed the word, wherever in the file it was.
The commit: git bisect
When you know main was good a while ago and is bad now, bisect does the search: it checks out the
commit halfway between, you say good or bad, and it halves again. With a script that exits 0 for good and
anything else for bad, git bisect run does the saying. Here the script is two lines, and the bug
is a line in a file:
#!/bin/sh ! grep -q bug api.py
$ git bisect start HEAD HEAD~4 Bisecting: 1 revision left to test after this (roughly 1 step) [7742196e73c4f9d00384d5d5b6fd8497d2fff238] api: handle the edge case $ git bisect run ./check.sh running './check.sh' Bisecting: 0 revisions left to test after this (roughly 0 steps) [8498150ec9ca1a65dbaa1d2658471bd99d3c9008] api: add the endpoint running './check.sh' 7742196e73c4f9d00384d5d5b6fd8497d2fff238 is the first bad commit commit 7742196e73c4f9d00384d5d5b6fd8497d2fff238 Author: ana <ana@example.com> Date: Sun Oct 4 12:04:00 2026 +0000 api: handle the edge case api.py | 1 + 1 file changed, 1 insertion(+) bisect found first bad commit $ git bisect reset Previous HEAD position was 8498150 api: add the endpoint Switched to branch 'main' Your branch is up to date with 'origin/main'.
Four commits, two steps, and the first bad commit with its full record. git bisect reset returns
to where you started. The usual script runs the test suite or the build; anything that can tell good from bad
will do, and the search is the same for forty commits as for four, a few steps more.
The name
The command is called blame and the practice around it is called blameless, and both are right. The commit is the fact; the person is not the finding. A post-mortem that stops at a name learns nothing about why the line looked right to everyone who read it.
Why the game does this to you
In Git Game a bug is printed on a card, and only its holder sees it, so a commit on main may hide
one until the release flips every commit face-up. blame is a card: play it on a face-down commit
on main, and if it holds a bug its author takes -3 blame now, with the commit left
face-up. bisect is in the tabletop deck, pointed at a range of main: its owner must
say which half holds a bug. It isn't played online yet.
Play a day where this happens
One tap starts a game against the bot, whose commits hide bugs as yours do.
Output captured from Git 2.50.1 (Apple Git-155) by scripts/git-output.sh, in a scratch repository with two clones, ana's and bot's, and fixed dates, so the hashes are the same on every run. It is captured again at every Git release.