Putting Jupyter notebooks under source control with Quarto
Posted on Tue 13 January 2026 in Software
Jupyter notebooks are an excellent way to provide interactivity.
Extremely helpful when building tutorials and demos. However, putting
Jupyter notebooks under source control is messy: the .ipynb format is
a JSON-based format that combines content (code and Markdown text) with
state information (outputs, version numbers, etc.), and you need to
clean up this information before committing or else Git gets very
confused.
Also, the fact that text has to live in separate cells from code tends to break down the flow when reading.
This is where Quarto is very useful. Quarto lets
you write code and text together in a single .qmd document, a Markdown
file. Code is interpolated using a variant on standard Markdown code
blocks. The file therefore consists solely of content, no metadata or
execution outputs.
Quarto offers a lot of features for publishing notebooks as a website,
as a PDF/ePub book, and other formats, but the most useful is its
feature to convert easily between .qmd and .ipynb. Here's a
Makefile for doing this:
SHELL := /bin/bash
.ONESHELL:
QMD := $(wildcard *.qmd)
IPYNB := $(QMD:%.qmd=build/%.ipynb)
VENV := .venv
notebooks: $(IPYNB)
build/%.ipynb: %.qmd
. $(VENV)/bin/activate
mkdir -p build
quarto convert $< -o $@
clean:
rm -rf build
.PHONY: all clean
Note that this is a Makefile so the indents need to be tab characters, not spaces.
To "compile" your .qmd files into Jupyter notebooks, simply run
make notebooks
The build/ directory will now contain the notebooks, which you can
distribute. It's a good idea to put build/ under .gitignore so that
only your .qmd files go under source control.