Articles

What Is Git Bisect? Finding a Bad Commit Fast

git bisect finds the exact commit that introduced a bug by binary-searching your commit history, cutting the search space in half each step.

The Lycoris Team The Lycoris Team · · 4 min read
Terminal window showing git commands

git bisect is a built-in git command that finds the exact commit that introduced a bug by binary-searching your commit history. You tell it a known-good commit and a known-bad one, and it checks out commits in between, asking you (or a script) to mark each as good or bad, until it narrows the culprit down to a single commit.

The value is in the math: a linear search through history means checking commits one by one until you hit the bad one. A binary search cuts the remaining range in half on every step, so a bug hiding somewhere in a thousand commits takes about ten checks to find, not up to a thousand. See what Big O notation is for why halving the search space each time — O(log n) — beats checking one at a time.

Running a bisect session

Start a session, then mark the two ends of the range:

git bisect start
git bisect bad                # HEAD is broken
git bisect good v1.4.0        # this tag was known to work

Git checks out a commit roughly halfway between the two and waits. You build and test that commit, then tell git what you found:

git bisect good   # this commit works — bug is later
git bisect bad    # this commit is broken — bug is earlier

Git checks out the new midpoint of whatever range remains and repeats. When only one commit is left, it reports that commit as the first bad one, along with its message, author, and diff. Run git bisect reset afterward to return to the branch and commit you started from — bisect leaves you in a detached-HEAD state while it’s active, similar to checking out a commit directly rather than a branch.

Automating it with a script

Manually testing each commit works, but it’s tedious for a bug that takes real setup to reproduce. If you can express “is this commit broken” as an exit code, git bisect run does the whole search unattended:

git bisect start
git bisect bad HEAD
git bisect good v1.4.0
git bisect run npm test -- --testPathPattern=checkout

Any command that exits 0 for good and non-zero for bad works — a test file, a build script, a shell one-liner that curls an endpoint and greps the response. Git runs it at each midpoint automatically and reports the first bad commit without further input. This is the form worth reaching for when a regression is easy to detect programmatically but tedious to check by hand: bisecting fifteen commits by eye is fine, bisecting a thousand is not.

Where it fits versus other debugging steps

Bisect doesn’t tell you why a commit broke something — it tells you which commit did, and once you have that, git log -p on the identified commit or git blame on the specific lines usually gets you the rest of the way. It pairs naturally with a git worktree: run the bisect in a second worktree so your main working directory, with whatever you were doing before the bug report came in, stays untouched. It’s also unrelated to git rebase — bisect only reads history, it never rewrites it, so it’s safe to run on a branch you don’t want to touch; see rebase vs merge if the distinction between reading and rewriting history isn’t clear.

git bisectChecking commits one by one
Steps for n commits~log₂(n)Up to n
Example: 1,000 commits~10 checksUp to 1,000 checks
RequiresA reliable pass/fail test per commitSame
AutomatableYes, via git bisect runOnly with the same test, run manually

The catch is the phrase “reliable pass/fail test.” Bisect assumes the bug is monotonic — that once it’s introduced, every later commit is also bad, with no good commits reappearing after it. Flaky tests, environment-dependent bugs, or a bug that was fixed and later reintroduced can confuse the search; git has a git bisect skip for commits that can’t be tested (say, a commit that doesn’t build), which excludes them from consideration without treating them as good or bad.

The takeaway

git bisect turns “find the commit that broke this” from a linear slog into a binary search, typically needing only a handful of checks even across a long history. Mark a known-good and known-bad commit, test each midpoint git hands you, and let it converge — or better, wrap the test in a script and hand it to git bisect run so the whole search happens unattended. It’s one of the highest-leverage git commands for the specific problem of “this used to work, now it doesn’t, and I don’t know when it changed.”

The Lycoris Team The Lycoris Team · · 4 min read

What Is Git Reflog? Recovering Lost Commits

Git reflog records every place HEAD and branch tips have pointed, letting you recover commits that look lost after a reset, rebase, or deleted branch.

#Git #Developer Tools #Version Control
The Lycoris Team The Lycoris Team · · 5 min read

What Are Conventional Commits? A Commit Convention

Conventional Commits structures commit messages as type(scope): description so tools can auto-generate changelogs and version bumps from git history.

#Git #Developer Tools #Version Control
The Lycoris Team The Lycoris Team · · 4 min read

Git Stash Explained: Shelve Changes Without Committing

Git stash saves uncommitted work to a hidden stack so you can switch branches cleanly. How stash, pop, apply, and stash branches actually work.

#Git #Developer Tools #Version Control