Building Apps with AILesson 31 of 87

Contents

Building Apps with AI

Lesson 31 of 87. Sign in to keep your place.

Module 4 · When it breaks, and getting back

Finding the change that broke it

8 min read

Halving the range instead of reading it010002000321024Commits between the working one and the broken oneVersions you have to open and try—— Read every diff– – Halve the range each timeFive checks find the culprit among thirty-two commits and ten among a thousand, because each checkremoves half of what is left. It costs nothing but the habit of small commits.
Five checks find the culprit among thirty-two commits and ten among a thousand, because each check removes half of what is left. It costs nothing but the habit of small commits.

Figure

The question that shortens everything

When did this last work?

If you can answer that with a commit, you have converted an open-ended debugging problem into a search through a list, and the list is short. This is the practical return on committing at every working state, and it is why the git lesson sits where it does in this course.

Look at what changed

Bash
git log --oneline -10          # the last ten save points
git diff HEAD~3                # everything since three commits ago
git log -p -- lib/queries.ts   # every change to one file, with diffs

That third command is the one people do not know about and it is excellent. When one file is behaving strangely, its complete history with diffs is often enough on its own: you see the moment the condition changed and you see what it was before.

Bisecting by hand

If twenty commits sit between working and broken, do not read twenty diffs. Halve the range.

Bash
git log --oneline -20        # find a commit from before the problem
git checkout a3f9c21         # go there, look at the app
# works?    the bug is newer
# broken?   the bug is older
git checkout main            # come back

Five checks find the culprit among thirty-two commits. Ten find it among a thousand. This is a large saving and it requires nothing but the discipline of small commits.

Git will do the halving for you with git bisect start, git bisect bad, git bisect good <commit>, and then git bisect good or git bisect bad at each step until it names the commit. Worth learning once you have used the manual version enough to trust it.

The uncommitted case

If you have not committed for three hours, the bisect route is closed and you have one weaker option:

Bash
git stash        # set aside everything since the last commit
# test the app
git stash pop    # bring it all back

That tells you whether the problem is in your uncommitted work or was there before. It does not tell you which part, because it is all one lump. Which is the lesson: the value of a commit is not the saving, it is the boundary.

What to do once you have found it

You now have a commit that introduced a bug. Three routes, in order of preference.

Read the diff and fix it. Usually the diff is small and, knowing that it contains a bug, you will often spot it in under a minute. Ninety percent of the time this is the answer.

Revert it. git revert a3f9c21 creates a new commit undoing that one, leaving the history intact. Right when the change was not essential and you would rather have the working app back today.

Rebuild it. If the change was a feature built through several rounds of patching, redo it from a cleaner description now that you know what went wrong. This is often faster than repairing, and it feels like defeat while being the cheapest option on the table.

Hand the culprit over, not the symptom

Text
This worked at commit a3f9c21 and is broken at 7e21b04.
The diff between them is:
[paste git diff a3f9c21 7e21b04]

The symptom: bookings at exactly the end time of another
booking are now refused.

Which line in this diff causes that? Explain before changing anything.

That is an enormously better request than a description of the bug, because it hands over the search space along with the problem. The model no longer has to guess where to look, and cannot wander into unrelated files while looking.

When nothing changed

Sometimes the code is identical and the behaviour is not. The variable is outside your repository: data that changed, a dependency that updated because a version was not pinned, an expired API key, a certificate, a third-party service having a bad day, or the clock: a bug that only appears after midnight UTC, or on the 31st, or when the month rolls over.

When a bisect finds nothing, stop bisecting and go looking outside the code. Check your host’s status page, look at the data the failing request touched, and check whether anything about it is new.

Every lesson here is open. Your progress is recorded once you pass the Building with AI exam.

Check your understanding

Bisecting finds that the bug exists in every commit including the oldest one you tested, yet the app worked yesterday. What does that mean?

Pick the one you would defend. Your answer stays private.

Next lesson · 8 minDependency trouble, and the lock file

Stuck on something?Ask Beatriz, your AI tutor

How to cite: Addaly (2026) ‘Finding the change that broke it’, in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/finding-the-change-that-broke-it (Accessed: 13 October 2026).