Jupyter Notebook(.ipynb形式)はインタラクティブな実行環境を提供する一方で、ブロックごとの出力や実行番号が必ずしもステートレスとはならず、gitで管理する時の壁となっています。具体的には、ipynb形式は出力や実行番号も内部に保存するので、管理の本質ではないdiffが多くなりコミットログを追うことが難しくなります。
本記事ではこれらに依存せずJupyter Notebookファイルをgit管理する方法をいくつか紹介します。
ただgit管理するだけではなく、以下の要求に着目しながら各方法を比較していきます。
- 手軽さ: 存在を意識せずに開発できるか。git管理することで余計な手作業は増やしたくありません。
- 環境依存性: pythonの場合、pyenvやpyenv-virtualenvなどといったpythonのバージョンやインストールしたpipモジュール群を切り替えるツールを使っている方も多いかと思うので、設定は各環境ごとに行えるのが理想です。
- 継続的な開発への耐性: Jupyter Notebookでは出力や実行番号は試行錯誤の跡として重要な役割を果たすことがあるので、それに対してケアできるのかに関しても言及します。
結論
上の要求をすべて満足した上でgit管理することは難しいですが、いくつか前提をおけば可能な場合があります。
方法1 Clear All Outputs
Cell → All Output → Clearを押すと実行順の番号や標準出力が全て消えます。とりあえずしのぐならこれ。
管理するipynbファイルが多い場合、手作業が多くとても面倒という問題があります。
方法2 jupyter_notebook_config.pyを編集する
公式ドキュメントで述べられている内容です。詳しくは https://qiita.com/mmsstt/items/6f8382afcc94f57861d4 が参考になります。概要は以下
- jupyter_notebook_config.pyにセーブ時にフックする処理を追加する。
- セーブ時に出力や実行順などを除いた.pyファイルが生成され、それを管理する。
ipynbファイルそのものを管理しているわけではないので、この記事の趣旨とは外れると思いますが、参考情報として紹介しました。
方法3 nbstripout
nbstripout: https://github.com/kynan/nbstripout
雑に紹介すると方法2を自動でやってくれるpipモジュールです。pipで導入するので、pyenvの中でコントロール可能です。
インストールは以下。
$ pip install --upgrade nbstripout
$ nbstripout --install --attributes .gitattributes
すると以下のような.gitattributesファイルが生成されます。これによって、git commit時に出力や実行番号を取り除いたipynbファイルがコミットログに適用されます。
*.ipynb filter=nbstripout
*.ipynb diff=ipynb
開発への影響として、コミットするとipynbファイル自体の出力が削除されてしまうので、試行錯誤の最中などの場合は注意する必要があります。また、事前にcheckpointを作成していれば、出力結果を振り返ることができます。
各方法比較
手軽さ | 環境ごとへの対応 | 継続的な開発への耐性 | |
---|---|---|---|
Clear | × | ○ | ○ |
jupyter_notebook_config | ○ | × グローバル設定を変更する | ○ |
nbstripout | ○ | ○ | △ commitするたびに出力が消える |
個人的にはnbstripoutは実質コマンド2つで設定が終わる割に恩恵が多いので、commitするタイミングさえ気をつければ、使ってみた感じ良いなと思いました。