Git bisect with merged commits
GitGit BisectGit Problem Overview
I have a history that looks like this:
* 3830e61 Add data escaping. (Bad)
* 0f5e148 Improve function for getting page template.
* aaf8dc5 Merge branch 'navigation'
|\
| * 3e667f8 Add icons.
| * 43a07b1 Add menu styles. (Breaks)
| * 107ca95 Add Responsive Nav. (Good)
* | ea3d736 Add ‘Admin’ notice.
* | 17ca0bb Update placeholder text.
|/
* f52cc34 Add featured image.
* 2abd954 Style placeholders.
I am trying to learn more and git bisect
, but am having trouble with this history. I know that 107ca95
is good and 3830e61
is bad. When I run a git bisect
, commits 107ca95..3e667f8
are ignored. I happen to know that 43a07b1
is the commit that introduced a regression, but it is never evaluated.
Here is roughly what I've done:
git checkout master
git bisect start
git bisect bad
git bisect good 107ca95
git bisect bad (multiple times)
No matter what I do, 107ca95..3e667f8
are never checked out to be tested.
Is there any way that I can essentially "flatten" the history during the bisect to test those commits? I know I can use an interactive rebase
to flatten the history, but I do not want to have to do that.
Git Solutions
Solution 1 - Git
This is a very old but unanswered question. I decided to investigate, and found that I could show that the behavior of Git is different to what the question says it is. One explanation is that Git improved the algorithm for bisect, or that the questioner made a mistake in marking commits.
> I am trying to learn more and git bisect, but am having trouble with this history. I know that 107ca95
is good and 3830e61
is bad. When I run a git bisect, commits 107ca95..3e667f8
are ignored. I happen to know that 43a07b1
is the commit that introduced a regression, but it is never evaluated.
I wrote some code to check whether it is evaluated or not. My test shows that it is evaluated. Run the code below and verify that a commit with message Add menu styles.
appears.
Further comments:
- "commits
107ca95..3e667f8
are ignored": Please note, that the commit you marked as "good" will not be evaluated because git already knows it to be good. - Please read the section "Bisection Algorithm" in this article by Christian Couder. Also the section "Checking merge bases" might be relevant.
- As mentioned above, the question was certainly using a different version then the one I used (Question is from 2013, Git 2.11 is from 2016).
Bisect run output
- Notice that first 'Add Admin notice' is checked (line 4) because that provides the most information. (Read "Checking merge bases" from article mentioned above.)
- From then on, it bisects the linear history as would be expected.
Solution 2 - Git
This is already answered
Basic idea - to find which commit from feature-branch breaks your master, you will have to reapply it on top of ea3d736 - relevant master HEAD.
Following is an example (from git doc)of test script which does that for you:
Solution 3 - Git
Warning: the git bisect
section regarding "Automatically bisect with temporary modifications" has been updated with Git 2.25 (Q1 2020).
(And git bisect --first-parent
is available with Git 2.29+ -- Q4 2020)
It involves the step where you reapply the commit you are testing on top of your relevant master
commit (which was ea3d736
in the OP's case)
The "git merge --no-commit
" needs "--no-ff
" if you do not want to move HEAD
, which has been corrected in the manual page for "git bisect
".
See commit 8dd327b (28 Oct 2019) by Mihail Atanassov (matana
).
(Merged by Junio C Hamano -- gitster
-- in commit fac9ab1, 01 Dec 2019)
> ## Documentation/git-bisect.txt
: add --no-ff to merge command
> Signed-off-by: Mihail Atanassov
> Reviewed-by: Jonathan Nieder
>
> The hotfix
application example uses git merge --no-commit
to apply temporary changes to the working tree during a bisect operation.
>
> In some situations this can be a fast-forward and merge
will apply the hotfix branch's commits regardless of --no-commit
(as documented in the git merge
manual).
>
> In the pathological case this will make a [
git bisect](https://git-scm.com/docs/git-bisect) run
invocation loop indefinitely between the first bisect step and the fast-forwarded post-merge HEAD
.
>
> Add --no-ff
to the merge command to avoid this issue.
git merge
mentions indeed:
> Note that fast-forward updates do not create a merge commit and therefore there is no way to stop those merges with --no-commit
.
>
> Thus, if you want to ensure your branch is not changed or updated by the merge
command, use --no-ff
with --no-commit
.
Solution 4 - Git
You can select the range of commits with the "git start" command. The synopsis of the command is:
git bisect start <bad> <good>
In your specific case I think the right command would be:
git bisect start 3830e61 107ca95