Skip to content

Instantly share code, notes, and snippets.

@wisq
Last active April 25, 2024 10:22
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save wisq/0fa021df52a3bd2485ac to your computer and use it in GitHub Desktop.
Save wisq/0fa021df52a3bd2485ac to your computer and use it in GitHub Desktop.
Protip: Bisecting a single commit

Situation: Some commit (on master, but not necessarily head of master) has broken things, but it's a big commit and it's not clear what part broke things.

% git checkout master
% git checkout -b bisect-branch
% git revert <offending commit>

(test here to make sure reverting fixed your problem)

% git bisect start
% git bisect good
% while [ "`git diff master`" != "" ]; do echo -e "y\nq\n" | git checkout -p master; git commit -m 'partial undo'; done

(test here to make sure we've recreated your problem)

% git bisect bad

Now just follow the bisect.

The while line has broken your commit up into small chunks, one commit per chunk. If a chunk has actually broken syntax (so you can't test either way), you can git bisect skip.

You can also s/master/any-reference-branch-or-tag-or-sha/g. And you can use s\ny\nq\n if you want even smaller chunks (but more risk of syntax errors).

@skissane
Copy link

skissane commented Jun 3, 2023

This is a great idea, but when I tried it in practice, I didn't get that great results.

You end up with a commit history in file name alphabetical order of changed files, and then linear order of changes within each file. Depending on the exact nature of the changes, sometimes that works very well, other times you will end up with some change early in that history dependent on some change late in it, with the result that almost every commit fails to compile and/or run.

Sometimes a better approach is to try reverting a changed file at a time; if reverting a particular file causes a syntax error/etc, just skip reverting it and then try reverting the next one. Once you've tried reverting them all, you can go back and try again from the start, since sometimes reverting a later file makes it possible to revert an earlier changed file which it depends on. With luck, you'll reduce it down to the single file which causes the breakage. If the changes in that file are complex, then the approach you propose here can be helpful in narrowing down which of those changes is the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment