A regression is a bug in which something that previously worked correctly stops working after a change to the code. Unlike a brand-new feature’s first defect, a regression is a step backward: behavior that was once correct has been broken, often as an unintended side effect of fixing something else or adding an unrelated feature. The term captures a particular kind of disappointment, because the system has regressed from a known-good state.
Regressions are insidious because they hide in code that nobody was looking at. A developer changing one module may, through a shared helper or a subtle assumption, break a distant feature that was not part of the work at all. Without a way to detect this, the breakage surfaces later, in production or in a user’s hands, far removed from the change that caused it.
The primary defense is regression testing: maintaining a suite of automated tests that encode the expected behavior, and re-running the whole suite after every change. A test that passed before and fails now points directly at a regression. This is the everyday value of a test suite. It is less about proving new code correct and more about noticing when old code silently breaks. Continuous integration systems exist largely to run these suites automatically on every change.
When a regression slips through and a test does not pinpoint the cause, version control offers a powerful technique: bisection. Git’s official documentation describes git bisect as a command that “uses a binary search algorithm to find which commit in your project’s history introduced a bug.” The developer marks one commit known to be “bad” and an earlier one known to be “good,” and the tool repeatedly checks out a commit “between those two endpoints” and asks whether it is good or bad, “narrowing down the range until it finds the exact commit that introduced the change.”
Bisection turns finding a regression from a guessing game into a logarithmic search. Across a thousand commits, binary search converges in about ten steps rather than a thousand. The technique is most powerful when each candidate commit can be tested mechanically, because git bisect supports running an automated script at each step and deciding good or bad from its exit code.
The combination is the point: a test suite catches most regressions immediately, and when one escapes, bisection over a clean commit history finds the culprit fast. Together they explain why disciplined teams treat both comprehensive tests and small, well-described commits as load-bearing parts of their defense against regressions.