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 consi
Is there any way of doing
--first-parent
with git bisect
Yes: with Git 2.29 (Q4 2020), "git bisect"(man) learns the "--first-parent
" option to find the first breakage along the first-parent chain.
See commit ad464a4, commit e8861ff, commit be5fe20, commit 0fe305a, commit 15a4802 (07 Aug 2020) by Aaron Lipman (alipman88).
(Merged by Junio C Hamano -- gitster -- in commit 47f0f94, 17 Aug 2020)
bisect: introduce first-parent flag
Signed-off-by: Aaron Lipman
Upon seeing a merge commit when bisecting, this option may be used to follow only the first parent.
In detecting regressions introduced through the merging of a branch, the merge commit will be identified as introduction of the bug and its ancestors will be ignored.
This option is particularly useful in avoiding false positives when a merged branch contained broken or non-buildable commits, but the merge itself was OK.
git bisect [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]
git bisect
now includes in its man page:
--first-parent
Follow only the first parent commit upon seeing a merge commit.
In detecting regressions introduced through the merging of a branch, the merge commit will be identified as introduction of the bug and its ancestors will be ignored.
This option is particularly useful in avoiding false positives when a merged branch contained broken or non-buildable commits, but the merge itself was OK.
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 preceding 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.
git rev-list --first-parent --merges --parents GOOD..BAD \
| sed 's/^[^ ][^ ]* [^ ][^ ]* //' \
| xargs git bisect good
(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 one-liner would give you:
G---o---o---o---o---o---o---B main project branch / / / G---x---G---x---G dependency \ / x' dependency project taskbranch
This would make bisect traverse only the commits on the main branch:
o---o---o---o---o---o
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 instruct git-bisect to only go through the first-parents of the merge commits by running the following command:
git bisect skip $(comm -23 <(git rev-list G | sort) <(git rev-list --first-parent G | sort))
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.