I'm aware that git bisect is branch-aware by design, so that if between good commit, G, and bad commit, B, you merged in a branch, it needs to take those changes into consideration as well, as the bug may be contained in the branch.
In my case I have a dependency as a side branch and I merge in changes to my main project from time to time. The dependency can be considered a library that has a different way of running, different build-system etc. from my main project, but I still want recent changes from it via merges to the main branch.
The problem is then that while bisecting in this scenario, you end up on non-compilable commits in the commits from the dependency.
I would really just want to consider each branch merge as a single commit while doing the bisection.
A workaround I've found so far is making a list of valid commits G..B with git log --first-parent, and then while bisecting, do git bisect skip if the current commit isn't in that list. That takes a lot of time though (lots of files to checkout/change for each skip).
So the question is: Is there any way of doing --first-parent with git bisect or providing a list of commits i feel are valid to be able to avoid checking out branches I know already are not compilable? How do we only check the commits marked o in the diagram?
G---o---o---o---o---o---o---B main project branch / / / x---x---x---x---x dependency \ / x' dependency project taskbranch
Edit: added diagram for clarity
Björn Steinbrink's answer works great, but recently started printing this:
Here's a more modern version of his solution using "git replace" instead of grafts:
Unfortunately, it is much slower for large repos (around 3 minutes for 150k commits);
git replace
doesn't seem to have a bulk-mode yet. You might want to restrict the rev-list to only the commits in scope of your bisect.To remove the replacements when you are done, you can
rm .git/refs/replace/*
.I thought of one possible solution, but I'm still hoping to find something more elegant:
Mark all second-parents of all merges into the main branch as good
Marking all remote parents of each merge as good will consider all the commits preceeding them as good (and as such skipped by bisect). This solution should also be generic enough to handle multiple merges from multiple branches, leaving only the commits on the main branch.
(replace GOOD and BAD with the relevant commits)
The regex in sed removes the first two commits of each line; the merge commit itself, and the first parent, leaving the rest of the parents (usually just the second one).
Given the history stated in the question, running the oneliner would give you:
This would make bisect traverse only the commits on the main branch:
If any of the merged branches are indirectly the cause of the problem, it will be discovered when you test the merge commit via bisect, which could be reason to investigate further on that branch.
You can make git treat you history as linear using grafts. To linearize the whole first parent history you can use:
Just drop the grafts file when you're done with the bisection.
You can instruct git-bisect to only go through the first-parents of the merge commits by running the following command:
You might be able to use
git bisect start --no-checkout
to avoid having to actually checkout the commit into the working tree. Then I suspect that you can dogit checkout BISECT_HEAD
for commits that you actually want to test (i.e. only first parent commits on the main branch). I have not tried this but I hope it would work.I don't see a one-step method, however, based on your current solution: git bisect skip can take a list of commits to skip. git log branchname will list commits on branch branchname. So this should let you specify the list of commits.
If your dependency and your main code live in different filesystem spaces, you can specify the paths to include with git bisect start. Depending on your code layout, that may be the best option. (Almost certainly is if you have a list of files that may contain the bug!)
The man page has details; the see also there is interesting reading, too.