The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,949 other followers

Binary search for finding problematic versions: install a specific version in homebrew and git bisect

Posted by jpluimers on 2020/04/14

I’ve used these excellent posts to find out which youtube-dl version started to exhibit troublesome NPO downloads, then later find the actual failing commit:

Why the effort? I needed an as recent as possible youtube-dl working on as many sites as possible because of some work preparation.

The first link is very important because brew versions and alternatives have stopped working some 6 years ago, even though they turn up high on Google searches for brew install specific version. Hence the quote from the first link:

Installing software packages on Mac is very easy with homebrew. You typically get the latest version, however often in production you do not have the latest version of a software package. Another use case is when you upgrade to the latest and you find out there is bug which blocks you doing something. In this case you would like to downgrade to the previous version until the bug is fixed.In both cases you need to install a specific version of a software package with homebrew on your Mac, which tends to be not that trivial. There is a lot of discussion about this on stackoverflow but some of them are outdated based on brew versions which is not available anymore.

Binary search through homebrew

Part 1: getting the versions you need

Start finding relevant commits and their version numbers; this means fiddling with the grep expression until you get it right.

The first line is really important: it switches to the directory in which git manages your homebrew/core repository so you can run git commands in it.

pushd "$(brew --repo homebrew/core)"
git log Formula/youtube-dl.rb | grep "\(^commit \|youtube-dl 2018\)"

Compare it to the list of versions already installed (those are in the Cellar at /usr/local/Cellar/youtube-dl):

$ brew list youtube-dl --versions
youtube-dl ... 2018.01.27 2018.02.11 2018.02.22 2018.02.26

I was missing these commits:

commit 7ff05a1d5bc5e387afce4f8e5047fa40c02a16cf
commit 78a7cec7944640b15098c2207ce09aeba9221364
youtube-dl 2018.02.04 (#23650)

This got them by checking out the right commits, then forcing HOMEBREW_NO_AUTO_UPDATE=1 before each install, then finally doing some cleanup:

pushd "$(brew --repo homebrew/core)"
git checkout -b youtube-dl.2018.02.08 7ff05a1d5bc5e387afce4f8e5047fa40c02a16cf
brew unlink youtube-dl
HOMEBREW_NO_AUTO_UPDATE=1 brew install youtube-dl
git checkout -b youtube-dl.2018.02.04 78a7cec7944640b15098c2207ce09aeba9221364
brew unlink youtube-dl
HOMEBREW_NO_AUTO_UPDATE=1 brew install youtube-dl
git checkout master
git branch -d youtube-dl.2018.02.08
git branch -d youtube-dl.2018.02.04

After this the list of versions is more complete (bot all youtube-dl versions make it to homebrew/core though):

$ brew list youtube-dl --versions
youtube-dl ... 2018.01.27 2018.02.04 2018.02.08 2018.02.11 2018.02.22 2018.02.26

Part 2: doing a binary search

A binary search is a series of trial and errors where each time you pick the middle one between failing and working.

brew switch youtube-dl 2018.02.26
youtube-dl -v -k

After a working step, one more cleanup is needed:

brew switch youtube-dl 2018.02.04
youtube-dl -v -k
rm Het\ is\ hier\ Autistisch\ -\ Onderwijs-BV_101386590.m4v

This zoomed in to 2018.02.22 being the first failing version. So at least part of the problem was a regression, but likely a change on the NPO side was part of the problem too.

Now you can switch either to the most recent working version, or the most recent failing one (the last case will automatically update in the future):

brew switch youtube-dl 2018.02.11
brew switch youtube-dl 2018.02.26

The git bisect

This turned out to be much easier than I hoped for, especially since youtube-dl has very clear numbering of their releases by means of their tags.

The first bits are to get the repository and ensure it has a clean state:

pushd /tmp
git clone
cd youtube-dl
git stash

Then start the bisect:

git bisect
git bisect bad 2018.02.26
git bisect good 2018.02.11

The last one indicates how many iterations you might need and on which revision you are. In my case:

Bisecting: 25 revisions left to test after this (roughly 5 steps)
[3d977fe4d268c0b23bfc093f09ea9f9cf51ee4da] release 2018.02.22

The loop

Now you do a series of tests, each ending with git bisect bad for a failure or a git bisect good for success. The whole binary search thing is being handled by the bisect algorithm implementation in git:

./youtube-dl -v -k

If it fails, then you do this:

git bisect bad

If it is working OK, then you do some cleanup, then a git bisect good:

rm Het\ is\ hier\ Autistisch\ -\ Onderwijs-BV_101386590.m4v
git bisect good

The git bisect command will again tell you the revisions to test and estimated steps, followed by the commit hash and commit description.

When steps is non-zero, continue the loop (;

The finish

This all ended with at least some of being a regression:

Bisecting: 0 revisions left to test after this (roughly 0 steps)
[ee706f1009a90e9911f31d01aa9eae41cc34e75b] [npo] Improve quality metadata extraction

Now you need one final statement to cleanup:

git bisect reset

Optimizing the process

You can even optimise the testing using for instance


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: