gitgit-bisect

Changes made by merge commits not found by `git bisect` or `git log -S --all`


I made a fix to a file, and committed it to my git repository.

Some time later, I found that it had regressed. I wanted to know in which commit the fix had been taken out, so I tried git bisect and git log --all -S TERM, where "TERM" was a string added by my fix and which appeared nowhere else in the project.

I found that git bisect blamed an unrelated commit, and I found that git log --all -S TERM only listed the commit in which I added TERM, and didn't list any commits as having removed it, even though it was no longer in the file at "master".

After some manual searching, I found that there had been a merge commit between two branches. One branch had my fix and one did not. The merge author had picked the branch without my fix (strange, as there was no conflict in the file).

My questions are:


Solution

  • Why does git log --all -S TERM not list the merge commit?

    You must add the -m option to it:

    git log -m --all -S TERM
    

    In order to understand why a special option is needed in that case, let's first look at the operation of git log -p which must include the changes in the listed history. As you can easily check, by default for merge commits changes are NOT shown. The reason is that a change is the difference between two revisions whereas for a merge commit we have three (or more) revisions. The -m option to git log addresses that problem:

    Diff Formatting

    ...

    -m

    This flag makes the merge commits show the full diff like regular commits; for each merge parent, a separate log entry and diff is generated. An exception is that only diff against the first parent is shown when --first-parent option is given; in that case, the output represents the changes the merge brought into the then-current branch.

    Then, assuming that git log -S works as if by processing the diff returned by git log -p you should admit that by default the merge commits would be excluded from the results. However, fortunately you can combine the -S and -m options in git log and it works as expected.