Why isn't 'git bisect' branch aware?

10,721

The problem here is that git bisect is branch aware. When you tell it that "dependent" is good and "test" is bad, and one of the changes between there is a merge commit, it knows that in order to figure out where the problem was introduced, it's going to have to look at commits a, b, and c - otherwise, all it would be able to tell you is whether or not it's broken as of that merge commit.

It sounds like what you're expecting is to test the combination of commit b with the changes from the other branch, which is content which doesn't exist in any commit, and git bisect only lets you test commits! In order to test that content, you'd have to do a series of test merges - check out b, merge dependent, let you test, then check out a or c, merge dependent, let you test again. You can very easily do git merge --no-commit dependent once it's left you at commit b, then do git reset --hard when done with testing before running git bisect good/bad.

Otherwise, if I've misunderstood you expect it not to test any commits on the merged branch, and only test the merge commit itself (you don't care which of a, b, or c broke it), simply tell it that everything on the merged branch is good. Even better if you know that a, b, and c have nothing to do with it. Then you know without even testing that they're good!

But the one thing that you can't expect is for git to completely ignore commits a, b, and c. It has absolutely no way of knowing whether or not their changes are relevant to your "bug", and their changes are part of the difference between your good and bad commits.

Share:
10,721
Hounaida
Author by

Hounaida

Hi! I'm Matthew, and I enjoy building software. I figure there's a continuum where ya must balance between complete hack and completely factored. I try err on the side of Quality, but who doesn't :). I draw from a background working largely with open source software and I enjoy the sweet spot hitting flow in great code from Vim.

Updated on June 09, 2022

Comments

  • Hounaida
    Hounaida almost 2 years

    I'm trying to find the source of a bug that's come up since a commit in the past day on a long lived branch (which will be released much much later) called feature-x.

    There's a bug though. I find behavior that I don't expect from my script which might have been introduced in any of the commit's up till now, specifically because features of master are used heavily in feature-x, but less so on Master itself.

    To test this behavior, I have to run my script, dependent.pl. But when bisect jumps half way down the code, my script doesn't exist on Master and so it's impossible to test.

    I believe this is because bisect pulls you out into a headless state, but in this case I really want to be in the context of this other history/changeset, and not floating in the ether.

    Before anyone jumps to hit the you're doing it wrong buzzer, our team likes merging branches in these situations as the metaphor works well for this situation, not rebase-ing.

    I'll demo this by creating a sample repo:

    git init
    
    echo 'sub f { print $_; }' > main.pl
    git add .
    git commit -a -m "inital commit"
    
    git branch feature-x
    git checkout feature-x
    echo 'main::f(1)' > dependent.pl
    git add .
    git commit -a -m "Starting work on feature X"
    git tag dev-1.0
    
    git checkout master
    echo "sub f { return 1; }" > main.pl
    git commit -a -m "sub f { return 1; }"
    echo "sub f { return 2; }" > main.pl
    git commit -a -m "sub f { return 2; }"
    echo "sub f { return 3; }" > main.pl
    git commit -a -m "sub f { return 3; }"
    
    git tag release-1.0
    
    git checkout feature-x
    git merge master
    
    echo 'print main::f();' > dependent.pl
    git commit -a -m "Updating call to f"
    

    So now you get a repo that looks like this:

    o Updating call to f ( Head of branch 'feature-x' )
    o Merge branch master onto feature-x
    |\
    | o sub f { return 3; } (TAG release-1.0) ( Head of branch 'master' )
    | o sub f { return 2; }
    | o sub f { return 1; }
    o | Starting work on feature X ( TAG 'dev-1.0' )
     \|
      o initial commit
    

    So I run the command git bisect start feature-x dev-1.0 expecting I'll be able to find what broke my code in dependent.pl, I end up on commit 'sub f { return 2 }' without my history of changes from feature-x (i.e. If I run ls, all I see is main.pl and dependent.pl is missing).

    This puts me in an untestable state. I cannot know if the current commit broke my work or not, nor can I say that commits on master broke it, so I can't say this commit is good or bad.

    How can I test what broke my current branch?