How do I run git bisect only on commits that changed a certain file?
Yes, you can. In the manpage, you find this line:
git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
so after --
, you put the paths of the files or directories.
For example:
git bisect start -- arch/i386 include/asm-i386
Git bisect allows you to avoid testing a commit (see "Avoiding testing a commit" in the man page): when you are bisecting, and git has chosen a commit for you to test, you can override its choice with git reset --hard <commit you want>
.
Using git log
, you can find the last commit that affected a file (or subdirectory) - this will return its hash:
git log -1 --pretty=format:%H -- path_that_you_are_interested_in
So, every time git bisect
suggests you a commit to test, you should run this command to ensure that you only test the commits that affected somepath
:
git reset --hard $(git log -1 --pretty=format:%H -- somepath)
Now, there is one more thing that we need to take care of. If there are no interesting commits (i.e. no commits that modify somepath
) between last checked good commit and the commit currently chosen by git bisect
, we may end up in a loop. To avoid this, we should use a conditional clause:
#!/bin/bash
last_good=$(git bisect log | tail -1 | sed 's/git bisect good //')
last_interesting=$(git log -1 --pretty=format:%H -- lily/)
if [ "$last_good" == "$last_interesting" ]; then
# there are no commits modifying somepath between previously
# tested and currently checked-out one, so it must be good
git bisect good
else
git reset --hard $(git log -1 --pretty=format:%H -- somepath)
fi