0

I have a git tree which looks like this:

master (test passes)
|
|
|  stable (test fails)
|   |
|   /
+---
|

There is a test which fails when run against the stable branch, but passes when run against the master branch. As it is a complicated multi-process test it's rather hard to debug.

Can I use git to find which commit from the master branch can be cherry-picked to the stable branch in order to fix the test?

There are many hundreds of commits on both branches so doing it manually would be painful.

SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
Rich
  • 926
  • 1
  • 9
  • 17
  • `git bisect` may be of help – luk2302 Feb 07 '22 at 17:22
  • 1
    Sounds like this might be a good use case for [`git-bisect`](https://git-scm.com/docs/git-bisect) -- [here is a good SO post about it](https://stackoverflow.com/questions/4713088/how-to-use-git-bisect). – Alexander Nied Feb 07 '22 at 17:22
  • I use `git bisect` frequently but I'm unclear how it is relevant to this. How exactly would you use it? – Rich Feb 07 '22 at 17:23
  • 3
    Figure out if it was passing or failing at the point they split. If it was passing, it was broken on `stable`-- if it was failing, it was fixed on `master`. In the former instance, we would `bisect` between `stable` and point where they split to see at which point it started failing and fix it. In the latter instance, we would `bisect` between `master` and where they split and find the commit at which the test began passing, and then `cherry-pick` that commit. Keep in mind there's no guarantee here- if the history is complex or the fix spread over several commits it might not be possible. – Alexander Nied Feb 07 '22 at 17:28
  • @Rich What are you finding unsuitable about using git-bisect on this particular problem? – Schwern Feb 07 '22 at 22:08

1 Answers1

1

There are many hundreds of commits on both branches so doing it manually would be painful.

This is a job for git-bisect.

Start the bisect, git bisect start.

You know it's failing on stable, mark it as bad. git bisect bad stable.

You know it's passing on master, mark it as good: git bisect good master

Bisect will now select a commit between the two and check it out. Run your test. If it passes, git bisect good. It it fails, git bisect bad.

Bisect will pick another commit. Do the same thing.

Repeat until Git finds the commit where it started failing. Because it is doing a binary search, searching hundreds of commits should take about 20-30 commits. You can automate the process by writing a script to do the build and testing and passing it to git bisect run my_script <args>.

This depends on a single commit being the cause of the failure. If you have not been testing consistently during development there might be a newer commit which introduces the bug again (a regression). You may need to bisect again beginning with a newer "good" commit.

For more details, see the git-bisect documentation. They provide very clear instructions. Also this answer.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • I had absolutely no idea `git bisect` could be used like this, thanks! – Rich Feb 07 '22 at 22:32
  • 1
    @Rich This is all I've ever used `git bisect` for! I'm curious what you've been using it for? – Schwern Feb 07 '22 at 23:25
  • Going back and forwards on the same branch. – Rich Feb 08 '22 at 18:14
  • @Rich And you didn't think it would work between branches. It will effectively check [`master...stable`](https://git-scm.com/docs/gitrevisions#_dotted_range_notations). That is, all commits reachable by master or stable, but not both. – Schwern Feb 08 '22 at 21:24