How do I run git bisect only on commits that changed a certain file? [duplicate]
Asked Answered
T

3

17

I have a bug that have been introduced a long time ago, and testing for it is painful. However, I strongly suspect that changes which introduced the bug happened in one particular source code file.

Can I run git bisect on a sub-set of commits that changed that one file?

Trochanter answered 13/9, 2013 at 12:55 Comment(0)
J
33

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
Jetta answered 13/9, 2013 at 14:29 Comment(2)
What is "arch"?Corie
'arch/i386', 'include/asm-i386' and, I guess, 'or' would be the paths that bisect is operating on. It doesn't really matter what they are -- silvio is just using them as examples. Presumably, based on context, 'arch' is the 'architecture' for a build, in this case, i386: en.wikipedia.org/wiki/Intel_80386 So in silvio's case, the bisect is being run because there would be some problem with the i386 builds that need to be found.Dak
G
1

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
Guajardo answered 13/9, 2013 at 13:15 Comment(3)
Updated to avoid potentially infinite loop.Belsen
Why not use git bisect skip if not marking commit that do not contain changes to suspected file as good?Malcommalcontent
Wouldn't this be slower? With my solution, even if bisect chooses a commit that doesn't interest us, we jump to the nearest "interesting" commit right away. OTOH, if there are 10000 commits in total, but only 10 of them matter, using skip would mean visiting lots of "uninteresting" commits on our way.Belsen
A
0

One technique is to create a temporary branch starting back at a known good location and simply copy across all [i.e. a script] the commits that touch that file, and then do a bisect on that temporay branch. That way you skip all the irrelevant commits.

This was discussed on the Git Mailing List within the last month or so $gmane/232114. The discussion did not identify an easy way to pre-skip commits that had no relevant changes (It's probably something that would be useful though - as they say, patches welcome)

Animate answered 13/9, 2013 at 13:16 Comment(2)
But you usually cannot get a branch that contains only commits changing some file and at the same time still works.Belsen
I was assuming that all of your mainline commits were 'good' at the time of the commit. Do you have an indicator of which commits were thought 'good' at the time of commit? Without that you have a real problem in scripting a revision walker that picks out those that were thought good for the bisect to work against.Animate

© 2022 - 2024 — McMap. All rights reserved.