How to `git bisect` only on one branch's commits?
There is no easy way to accomplish this without further work. After playing with it for a little while I have something that might help you.
git bisect start master f9d5924for rev in $(git rev-list f9d5924..master --merges --first-parent); do git rev-list $rev^2 --not $rev^done | xargs git bisect skip
This starts git bisect with f9d5924
as your good commit and master
as your bad commit. Then it finds the ancestors of the right side of each merge commit that are not on the left side. It passes those ancestors to git bisect skip
to skip them. However when it figures out which commit is bad it will show all possible skipped commits from the bad merge commit. like the following
$ git bisect goodThere are only 'skip'ped commits left to test.The first bad commit could be any of:0622204625d8817c5d8fd1a2a68b3aa91f2dcdf90c771566b9e77e3bdc0a66a7404c8eae9f321a685098b44f43f84b213eaab110073a6acd26a5cc028b05a808d5e15852fbddaa529ba241fdac8ff693b0c755c3fa57e3c8d527e76fae38bc9925c01353We cannot bisect more!
In this case b0c755c3fa57e3c8d527e76fae38bc9925c01353
was the merge commit it failed on.
Note: This will not work if you have an octopus merge (a merge that merges more than two branches together).
I too would like a proper and native-to-git solution to this question, only checking commits on a single branch and thus "blaming" an entire merge and/or Pull Request. However:
since the master branch's commits are the only (supposedly) stable ones, I want to git bisect only on that branch.
If the issue prompting this question is that some of the commits you're being given are broken and you cannot test, you can use:
git bisect skip
To skip that commit entirely and check a different one. This will solve the problem you're having with broken commits. Once you find the commit that broke the feature, you can follow it to the merge into the branch you're tracking.
I suppose you could even git bisect skip
ALL commits that are not merges, either by manually checking or via a script. That would give the behavior asked in the question.
I think git bisect
with a --no-parent
flag could do this easily, but it doesn't exist.
The only thing I can think of involves recreating just the branch commits in a new branch. Here's an example in the Linux shell:
$ git branch bisecttemp <first>$ for h in `git log --oneline --decorate --first-parent --reverse --format=%H <first>..<last>`; do git checkout -f $h; sleep .5; git reset bisecttemp; git commit -am"$h"; git checkout testing; git reset --hard HEAD@{1}; done
That makes a bisecttemp branch off the <first>
commit we care about, gets a list of just the hashes between the <first>
and <last>
commits in the range we care about, visits each, resets back to the bisecttemp branch after each, without changing the working tree, commits everything different with the hash of the commit it came from, checks out bisecttemp again, and then resets it back to the last place head was, which is the new commit.
There may be a smarter way to do all of this, but the basics are that it creates a new branch off the start of the range of commits we care about, then commits the state of the branch-only commits (regular commits and merges, but not any sub-branch commits) to it, in order. You can't just cherry-pick here, as cherry-picks look at parents, and that would fail on the merge commits.
This isn't really tested, and could all be wrong. It's just a thought. It could all be rolled up in a function that takes a range of commits.