Version Python notebooks with Git
marimo eliminates large Git merge conflicts and CI/CD challenges in Python notebooks by storing everything as clean Python files instead of JSON.

Version control is one of the biggest frustrations in the notebook ecosystem. Anyone who has worked with them in a team setting knows the pain: cryptic merge conflicts in JSON files, noisy commit histories filled with execution count changes, and the impossibility of running notebooks in CI/CD pipelines without jumping through hoops.
Instead of complex JSON files that mix code, metadata, and outputs, marimo are stored as .py files. This simple change transforms notebook development from a Git nightmare into a smooth, collaborative experience.
Why Git is better with marimo
With marimo, small changes to your Python file yield small Git diffs, because marimo notebooks do not store metadata and cell outputs. Merge conflicts are also easy to resolve, because the code is just Python. For when you do want to store outputs, you can export your notebook to HTML or IPYNB, either from the command-line or periodically while you are editing.
This approach makes code reviews meaningful. Instead of reviewers struggling to parse JSON diffs that show structural changes rather than logical ones, they can focus on the actual code changes that matter. Pull requests become readable, and the review process becomes about the science and logic rather than fighting with file formats.
Python notebooks for CI/CD
While the Python file format is great for Git, it also integrates with pytest. When the optional pytest dependency is present, marimo runs pytest
on cells that consist exclusively of test code. So your tests can ship with your notebook and are easily accessible from CI.
This integration enables powerful workflows that were difficult or impossible with traditional notebooks:
- Automated testing: Your CI pipeline can run
pytest
directly in marimo notebooks, ensuring your analysis remains correct as data and dependencies change - Regression testing: Check that your analysis produces expected outputs when run against known datasets
- Data validation: Include tests that verify data quality and assumptions directly in your notebooks
- Reproducibility checks: Automatically verify that notebooks can be executed from scratch in clean environments
The pytest integration also supports standard testing patterns such as fixtures, parameterized tests, and custom assertions. You can program tests that validate your data transformations, check statistical assumptions, or ensure that visualizations contain expected elements.