git bisect
Advanced Git CLI Careful
Summary: git bisect finds the first commit where something broke, by checking out midpoints and asking you, or a script, whether each one is good. Ten answers cover a thousand commits.
Careful — it checks out old commits, leaving you in detached HEAD until git bisect reset. Commit or stash your work first.
What it does
Takes one commit known to be bad and one known to be good, then repeatedly checks out the commit halfway between them and narrows the range according to your answer, until one commit remains.
Why it exists
"It worked last month" describes a range of a few hundred commits. Reading them is impractical, and a binary search turns the problem into a handful of checks.
When to use it
- Behaviour changed and you do not know which commit changed it.
- A test that used to pass now fails.
- A document that used to build now does not.
When not to use it
- When you know the string that appeared:
git log -Sis instant. - When the question is about one line:
git blame. - With uncommitted work in the tree. Stash it first (
git stash).
Syntax
| Form | Effect |
|---|---|
git bisect start <bad> <good> |
Begin, naming both ends |
git bisect good / git bisect bad |
Answer for the current checkout |
git bisect skip |
This commit cannot be tested |
git bisect run <script> |
Answer automatically: exit 0 is good, non-zero is bad |
git bisect log |
What has been answered so far |
git bisect replay <file> |
Re-run a saved session |
git bisect reset |
Stop and return to where you started |
git bisect start with no arguments also works: mark the ends afterwards with git bisect bad and git bisect good <commit>.
Examples
Automatically, with a script that greps for a string that should not be there:
$ git bisect start HEAD HEAD~6
$ git bisect run ./check.sh1e90067a1457fd9969319c1a97c12bedde7f7ea7 is the first bad commit$ git bisect reset
By hand, when the check is "does the page look right?":
$ git bisect start HEAD v1.2.0
# Git checks out a midpoint; look, then:
$ git bisect good # or: git bisect bad
# repeat until Git names the commit
$ git bisect resetExpected result
A line naming the first bad commit and showing its message and diff summary, then git bisect reset returns you to your branch.
Common mistakes
- Forgetting
git bisect reset, leaving the repository detached (lesson 12.5). - A script that depends on uncommitted files, which are not there at old commits.
- A script that always fails, for example because an old commit cannot build; use
git bisect skipor make the script exit 125, which means "cannot test". - Naming good and bad the wrong way round, which searches the wrong half; Git will say "there are only skipped commits left" or find nothing sensible.
- Bisecting with a dirty tree, which Git refuses.
How to undo or recover
git bisect reset always returns you to the branch and commit you started from. If you interrupted it and are unsure, git bisect log shows the session and git bisect reset still works.
In VS Code
No interface; use the integrated terminal (lesson 15.9).
In IntelliJ IDEA
No interface either; the terminal (⌥F12) is the tool (lesson 16.10).
On GitLab and GitHub
Neither platform bisects. What they contribute is the pair of endpoints: a release tag that was good, and today's main that is bad.
Related commands
git log with -S when you know the string · git blame for a line · git switch to return afterwards · git stash before starting.