git bisect: find the commit that broke the project
Updated July 31, 2026
git bisect binary-searches for the first commit that broke the project: you name a good commit and a bad one, and git halves the range until a single culprit is left.
The situation is a familiar one. It worked a week ago, it does not work today, there are fifty commits in between, and nobody remembers which one touched what. Checking them one by one takes an afternoon. Halving the range takes about six checks: every answer throws away half of what is left.
The search starts from two points. The current state is broken, so bad is HEAD. Take the hash of a working commit from git log --oneline, scrolling the history back a week.
$ git bisect start
status: waiting for both good and bad commits
$ git bisect bad
status: waiting for good commit(s), bad commit known
$ git bisect good 043bb10
Bisecting: 12 revisions left to test after this (roughly 4 steps)
[d93426ddd5d982dd2d13a8334ecbdb6ab024dbab] new page gridGit has moved to the middle of the range and rewritten the working directory to match that commit. Your turn now. Do whatever it was that showed you the breakage: open the page, or run the tests. The answer you give git is one word.
$ git bisect good
Bisecting: 6 revisions left to test after this (roughly 3 steps)
[2ea20760160b06f0def0a625788535218d126ee8] renamed the grid classes
$ git bisect bad
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[15a5be35a1027b2caae3b3c858b160f338be327d] dropped an extra div
$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[387e18d65958f85d2578a95272fa05b91ca3272a] fixed the menu spacingOne more answer and the range collapses to a single commit:
$ git bisect good
2ea20760160b06f0def0a625788535218d126ee8 is the first bad commit
commit 2ea20760160b06f0def0a625788535218d126ee8
Author: Anna Petrova <anna@example.com>
Date: Wed Mar 19 10:00:00 2025 +0300
renamed the grid classes
index.html | 2 ++
1 file changed, 2 insertions(+)That is the answer: twenty-six commits, four checks. Now close the search, or you stay parked in the middle of the history:
$ git bisect reset
Previous HEAD position was 387e18d fixed the menu spacing
Switched to branch 'main'When the check can be automated, git walks the whole path on its own. git bisect run <script> runs the script at every step and reads its exit code: zero means the commit is good, anything else means bad. Any command with an honest exit code will do, from a test suite to a grep over a file.
Common mistakes
Forgetting git bisect reset. For the whole search you sit in detached HEAD, and git status says so plainly: You are currently bisecting, started from branch 'main'.. A commit made in that state belongs to no branch. When the search is over, run reset right away and it puts you back on the branch you started from.
Second, mixing up good and bad. Git takes your answers on trust and builds the search around the mistake. If you lose track, git bisect log prints the whole chain of answers, and git bisect reset lets you start over.