How to `git bisect` only on one branch's commits?
Asked Answered
I

3

39

In a project I am currently working on, we keep each feature its own brach and merge it back to master when the feature is ready. The commits inside each feature branch might include a lot of "WIP" and breaking functionality of other features until it is complete and stable.

Anyway, since the master branch's commits are the only (supposedly) stable ones, I want to git bisect only on that branch.

Is there a way to limit git bisect only on one branch?

Ireful answered 27/11, 2013 at 10:56 Comment(1)
Possible duplicate: #5638711Chayachayote
H
27

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 f9d5924

for 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 good
There are only 'skip'ped commits left to test.
The first bad commit could be any of:
0622204625d8817c5d8fd1a2a68b3aa91f2dcdf9
0c771566b9e77e3bdc0a66a7404c8eae9f321a68
5098b44f43f84b213eaab110073a6acd26a5cc02
8b05a808d5e15852fbddaa529ba241fdac8ff693
b0c755c3fa57e3c8d527e76fae38bc9925c01353
We 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).

Hey answered 27/11, 2013 at 17:26 Comment(1)
I think git bisect needs a --first-parent flag, with a description in the help of what that entails. It would only traverse the commits and merge commits of the actual branch, and not its merged-in branches or branch bubbles. You'd either find the commit on your branch, nestled between others, or you'd finish up on a merge commit, and know that the issue was somewhere in the branch that merged in at that point.Asomatous
S
2

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.

Shank answered 28/6, 2017 at 16:47 Comment(0)
A
0

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.

Asomatous answered 2/12, 2013 at 11:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.