Tips

Homebrewで過去バージョンのアプリをインストールする方法

Homebrewで何かをインストールする場合、デフォルトでは最新のバージョンがインストールされます。訳あって過去のバージョンのものをインストールしたい場合の説明がネット上に少なかったので記載しておきます。

ライセンスを持っている古いSketchを使いたかった

最近Macを買い替えたのですが、アプリは移行アシスタントを使わずに一つ一つインストールし直すことにしました。Sketchというデザインアプリを使っているのですが、以前は買い切りでずっと使えていたのですが、最近のバージョンはサブスクリプションになっていました。最低限の機能が使えれば良いので、追加の費用を払って最新バージョンにするのも嫌だったので、元々使っていたバージョンをインストールすることにしました。

そのバージョンのインストール用のdmgファイルは普通に公式サイトからダウンロードできるので、手動でインストールするのは簡単です。でも今回のMacからはHomebrewでインストールにこだわりたいと思っていました。

前のMacではCUIアプリはhomebrewでインストールしていましたが、GUIアプリはHomebrewを使うものもあればそうでないものもあり、中途半端な管理をしていました。でも、今回のMacからはhomebrewでインストールできるものは必ずhomebrewでインストールして、一元化しようと考えていました。Homebrewの何が良いのかは次の記事で説明しました。

Homebrewとは?本質的な価値を解説。何ができる?メリットは?Macで何かをインストールするための記事でよく紹介されるHomebrewって一体なんなのでしょうか?検索して調べてもわかったようでわから...

Formulaを対象のリビジョンに戻す

いくつかネットに載っていたやり方を試したのですが、以下が最も参考になりました。

brewで過去のバージョンをinstallしたいンゴ

でも完全にこの通りやっても上手く行かなかったので、結局これを応用して自分でやり方を考えました。使ったバージョンを記載します。

Mac OS 13.0(22A380)
Homebrew 3.6.18

※追記で4.0.26にも対応

まずFormulaがあるディレクトリに移動します。(Caskの場合はFormulaと呼ばないのかな?本記事ではまとめてFormulaと呼びます。)

homebrewのcoreに入っているアプリなら /opt/homebrew/Library/Taps/homebrew/homebrew-core/Formula となります。これらのパスはM2などのApple Silliconの場合です。従来のIntel Macをお使いの方は、パスが違うとのことなので調べてみてください。

ちなみに、Homebrewの4系以降だとこのディレクトリがローカルに存在しない可能性があります。 brew tap で確認できます。

ご自身のご希望のものがなければ、

などのようにして、落としてくるとことが可能です。

このディレクトリでlsをする場合はとんでもない数のファイルが表示されてしまうので注意しましょう。念のため対象のアプリのFormulaが存在しているか確認します。sketchという部分はFormula名なので、対象のものに置き換えてください。

git logで対象のコミットをかくにんします。私の欲しいバージョンは51.3なので、7行目となります。このコミットIDをメモります。

Formulaを対象のリビジョンに戻します。

中身を確認してしてversionが狙ったものになってるか確認します。

自動アップデートとAPI経由せずにインストールする

1行目について説明します。通常 brew installすると、自動的に先に brew update が走ってしまいます。そうすると、せっかく狙っているリビジョンに戻したFormulaがまた最新のものになってしまい、狙ったバージョンではなく最新版のアプリがインストールされてしまいます。なので、 HOMEBREW_NO_AUTO_UPDATE=1 という環境変数をつけて brew update が走らないようにします。次の記事を参考にしました。

Mac Homebrewのbrew tapでも自動アップデートがかかって余計な出力が出るので注意

HOMEBREW_NO_INSTALL_FROM_API=1 は4系から必要になったオプションです。軽く上述しましたが、4系ではFormulaやCaskは基本的にローカルには配置せず、その都度APIから取得します。この環境変数をつけないで、 brew installすると、APIから取得した最新のFormulaやCask(実際はJSON形式ですが)を使って、インストールしてしまいます。なので、せっかくローカルでFormulaやCaskを過去のバージョンに戻しても使われないのです。この環境変数をつけると、ローカルのものを使ってインストールしてくれます。

4系のこの変更はかなり暴力的な変更ですよね。私の場合は、勝手にHomebrewが自動的に4系にアップグレードされて、この仕様変更がされていたので、最初、あるソフトウェアのバージョンを戻そうとした時、最新版しかインストールしてくれなくて何時間も沼にハマりました。どうやって気がついたかというと、以下のよう --debug オプションをつけてようやくヒントに至りました。

ここの loading libxml2 from APIというのを見つけて検索をしてみたら、APIから、つまりインターネット上からFormulaやCaskをロードする仕組みができたことを知りました。さらにHomebrewの4系からその挙動がデフォルトになっているということがわかりました。

調べていくとこの HOMEBREW_NO_INSTALL_FROM_API=1をつけることで従来通りの動きをしてくれることがわかりました。

確かに、多くの人は最新版さえインストールできればいいので、ローカルに大量のFormulaやCaskのファイルを配置しておくのはディスクの無駄と言えます。でもそれなら、API経由でも過去バージョンをインストールする方法を準備してくれていればいいのに、いくら探しても出てきません。仕方ないので、このローカルのFormulaやCaskを過去のものに戻す、という方法を採用しています。

ちなみに、 HOMEBREW_NO_AUTO_UPDATE=1 は、毎回のコマンドで指定するのではなく、シェルの環境変数に記載してしまった方がいいです。以下の記事に書きましたが、Hombrewのコマンドを叩くたびに自動的にソフトウェアがアップデートされると、依存関係が壊れて何かしら動かなくなる可能性が高いです。こちらはHomebrewを使うかた全員にお勧めしたいです。

Homebrewの自動アップデートを止めよう!開発環境が壊れる前にMacのソフトウェアをHomebrewで管理していて起きる問題の、最も多い原因は自動アップデートによるものだと感じます。問題の事例とその...

そして、過去バージョンを使う可能性がある方は、 HOMEBREW_NO_INSTALL_FROM_API=1 もシェルに設定してしまった方がいいです。せっかく過去バージョンをインストールしたのに、何かのタイミングでAPIから最新版をインストールしてしまうかもしれません。

やり方としては、私の場合は、.zprofileに以下を追記しました。

利用中のターミナルのセッションでこれを反映させるためには、

を実行します。

なお、環境変数がきちんと設定できたかを確認するには、

を実行して表示される中に、

が表示されていればOKです。

なお、.zprofileなどの設定ファイルを頻繁に編集するようであれば、これらをGitで管理するのがおすすめです。そのためにdotfilesというディレクトリを作って管理する方法を以下で説明しています。

dotfilesのシンプルな作り方と管理法!Macのzshユーザ向けMacでzshの設定や環境変数の設定、Gitの設定などをしだすと、設定ファイルを頻繁に編集することになります。.zprofileや.gi...

あと、zshの設定をどのファイルに記載するべきかにいくつか考え方があります。それについて以下で考えてみました。

.zprofileか.zshrcか.zlogin!どれを使うべきか?Macでターミナルなどでデフォルトで使われるシェルがbashではなくzshになりましたが、設定をどこに記載するか迷います。.zprofi...

バージョンを固定する

先ほどの環境変数をシェルで指定してしまえば、勝手にアップデートされることはないですが、別に全部固定しなくても特定のものだけ固定し、それ以外は自動アップデートされてもいいという場合の方法をご紹介します。

せっかく狙ったバージョンのアプリを最新版にされないために固定します。ここからは次の記事を参考、というかそのままやりました。

HomebrewでCaskのバージョンを固定する方法

Homebrewのcoreに入っているアプリなら、

で行けますが、今回はCaskに入っているアプリなのでこれができません。

なので、Caskを管理するためのツールをインストールします。

brew tap でインストールできるというのがよくわからないですが、これで使えるようになります。

以下で固定されます。

確認するには、

とします。

残る疑問、アンインストール時はどうなるの?

HomebrewのFormulaは何かと自動的にアップデートされる仕組みになっているので、sketch.rbもすぐに最新版になってしまうと思います。でも、Formulaには以下の16〜25行目のようにアンインストール時の処理も記載されています。設定ファイルなどを削除する処理のようです。

当然このあたりの処理もバージョンによって違いうるということだと思います。なので、このファイルが現在インストールされているバージョンと齟齬があった場合、適切にアンインストール時の処理がされるのだろうか?という疑問が残りました。

インストールされているFormulaがどこかに保存されていて、アンインストール時に使われるのかと思ったけど、見当たりませんでした。

まぁ、基本的にこの辺りの設定ファイルが消されなかったとしても、ゴミが残るだけで大した問題はないと思いますし、より新しいバージョンにアップグレードする場合は、上書かれるということだと思うので大きな問題はないはずですが、ちょっと気持ち悪いですね。

今後この辺りのHomebrewの細かい挙動を理解できればと思います。

他に試した方法

Homebrew Cask で特定のバージョンを指定してインストールする

この方法はうまく行かなかった。

とあるが、 tmp.rb のような適当なファイル名じゃダメで、以下の記事のように

Homebrew: How do you specify a version using brew cask?

のようなファイル名にしなければなりません。また --cask が無いと余計なエラーの表示が出ます。エラーが出てもよしなにインストールはしてくれます。

とはいえ、これはわざわざFormulaのファイルを手動でダウンロードしてくるやり方なので、私が前述した方法の方がスマートだと思います。