nbdime: Diffing and Merging Jupyter Notebooks Without JSON Noise
Tools for diffing and merging of Jupyter notebooks.
At a glance
- What is it?
- nbdime is a Jupyter subproject that compares and three-way merges .ipynb files at the level of cells and outputs instead of raw JSON. It ships CLI tools, a browser diff, and git and Mercurial integration, but it only makes sense if your notebooks are the thing under version control.
- Who is it for?
- Adopt nbdime if your team keeps .ipynb files in git or Mercurial and reviewers currently read raw JSON diffs. Skip it if notebooks are generated artifacts, if you strip outputs before committing, or if your workflow already lives in Jupytext text files.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 112 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem nbdime solves: notebooks are JSON, not text
A .ipynb file is a JSON document. Cell sources, outputs, execution counts and metadata all sit in one structure, and any tool that treats it as plain text sees that structure as syntax noise. Move one cell and a line-based diff reports a large block of changed lines. Re-run a notebook and every execution count and output payload shifts. Reviewers end up scanning escaped strings to find the one function that actually changed.
nbdime is aimed at people who keep notebooks under version control and need to review or merge them. The README lists the audience implicitly through its tools: nbdiff for terminal comparison, nbmerge for three-way merges with automatic conflict resolution, nbdiff-web for a rendered diff, nbmerge-web for a browser merge, and nbshow for presenting a single notebook in a terminal. That is a workflow for data scientists, research groups and platform teams who treat a notebook as a source file rather than a build artifact.
How nbdime compares notebooks: structure first, then content
The repository layout shows a split between a Python package under nbdime/ and JavaScript packages under packages/, managed as npm workspaces with lerna and TypeScript. The Python side parses notebooks with nbformat and produces the structural diff; the web tools render it. The pyproject.toml entry points map each command to a module: nbdiff, nbmerge, nbshow, nbdiff-web and nbmerge-web all have their own console scripts.
That separation is the design decision worth noticing. Because the diff is computed over notebook semantics rather than lines, nbdime can compare cells, outputs and metadata as distinct things. The README describes nbmerge as a three-way merge with automatic conflict resolution, which is the part that matters in practice: a three-way merge needs a common ancestor, so the tool is doing more than picking between two versions. The web variants exist because a structural diff of outputs is hard to read as text; the README's screenshots show rendered notebook content side by side rather than escaping.
The cost of this approach is that the diff is only as good as the notebook parser. Anything nbformat cannot interpret is outside the comparison model.
Installing nbdime and running your first notebook diff
The README gives one install line for the released package. Run it in the same environment where you launch Jupyter, since the console scripts land on that environment's PATH.
pip install nbdimeAfter that, nbdiff, nbmerge, nbshow, nbdiff-web and nbmerge-web should be available as commands. The README's tool list is the fastest way to confirm the install worked: ask for one of them and see whether the shell resolves it.
To compare two notebooks in the terminal, pass both files to nbdiff. The README describes this as a terminal-friendly comparison, so expect cell-level output rather than raw JSON lines. The README does not print a full invocation for this, so check the documentation for the exact argument order before scripting it.
When a text diff is not enough, nbdiff-web opens the rendered comparison in a browser. The README presents it as a rich rendered diff of notebooks, and the same caveat about argument order applies.
For version control integration, nbdime ships a configuration helper, and the README points to the installation documentation for the flags. A development install, for anyone working on the browser script code, is the one command the README does print in full.
pip install -e git+https://github.com/jupyter/nbdime#egg=nbdimeWhere nbdime stops being the right tool
The biggest limitation is not in the diff algorithm, it is in what gets stored. Notebook outputs are part of the file. If two people run the same notebook and produce different output payloads, nbdime will report differences in those outputs, and a merge has to decide what to do with them. That is a data problem the tool cannot solve for you; it can only make the differences visible. Teams that strip outputs before committing sidestep this, but then they lose the rendered diff that makes nbdiff-web worth using.
Second, nbdime is notebook-specific. Point it at a .py file and you are using the wrong tool. The README frames the whole project around Jupyter Notebooks, and the dependencies (nbformat, jupyter_server, jinja2) reflect that scope.
Third, the version control integration is opt-in. Nothing in the README suggests that installing the package changes how git treats .ipynb files; the configuration step has to be run for each repository or globally. A team that installs nbdime and assumes git will now merge notebooks correctly will still get text merges until that step is done. The README does not document rollback for the configuration, so plan for it before running it across a shared machine.
nbdime against a text-file workflow like Jupytext
The obvious alternative is not another diff tool, it is removing the problem. Jupytext keeps a notebook in a plain text format (a paired .py or .md file) so that ordinary git diffs and merges work without any notebook-aware machinery. The difference in approach is fundamental: nbdime adds structure awareness to a JSON file, while Jupytext changes what is stored so that line-based tooling is sufficient.
Which one fits depends on what you need to see. If reviewers need to inspect rendered outputs, plots and tables, nbdime's rendered diff is doing something a text diff cannot. If the notebook is a thin wrapper around code and the outputs do not matter for review, Jupytext removes an entire category of merge conflict. The two are not mutually exclusive in principle, but choosing one as the primary review path keeps the workflow legible. nbdime also carries a browser component and a JupyterLab extension, so it is the heavier of the two to install and keep current.
Maintenance, releases and upgrade cost
The repository is not archived, and the last push was on 2026-06-10, which is recent enough that the project is being touched. Releases are less even: v4.0.4 landed on 2026-02-10, v4.0.3 on 2026-01-15, and v4.0.2 before that on 2024-09-05. The gap between v4.0.2 and v4.0.3 is roughly sixteen months, so treat the release cadence as slow and plan upgrades around it rather than expecting frequent patch drops.
On the Python side, pyproject.toml requires Python 3.10 or newer and depends on nbformat, colorama, pygments, tornado, requests, GitPython, jupyter_server and jinja2. GitPython carries a pin excluding 2.1.4, 2.1.5 and 2.1.6, which the comment ties to taking git refs in the difftool. The JavaScript side is managed with lerna and npm workspaces, and the root package.json pins several transitive HTTP packages through an overrides block. For an upgrade, that means both a Python environment and a Node toolchain can be involved if you work on the browser components; a plain pip install does not require npm.
Licensing: the README states that all code is licensed under the terms of the revised BSD license, and pyproject.toml points the license field at LICENSE.md and classifies the project as BSD. The repository metadata reports the license as NOASSERTION, so the classifier and the README text are the clearer sources. The README also describes a shared copyright model in which contributors keep copyright on their contributions. That combination is permissive, but redistribution still requires keeping the copyright notice and licence text; this is a description of what the files say, not legal advice.
Editorial conclusion
Adopt nbdime if your team keeps .ipynb files in git or Mercurial and reviewers currently read raw JSON diffs. Skip it if notebooks are generated artifacts, if you strip outputs before committing, or if your workflow already lives in Jupytext text files. Before trusting it, run nbdiff on a branch pair from your own repository and check whether the diffs it reports are the ones your reviewers care about, then decide whether to enable the git integration described in the installation documentation.
Frequently asked questions
how to use nbdime
Install it with pip install nbdime, then use the commands the README lists: nbdiff for a terminal comparison, nbdiff-web for a rendered diff in the browser, nbmerge for a three-way merge, nbmerge-web for a browser merge, and nbshow to present a single notebook in the terminal. Version control integration is a separate step, and the README points to the installation documentation for it.
How do I install nbdime?
The README gives a single command, pip install nbdime, and links to the installation documentation for further detail and development installs. A development install uses pip install -e git+https://github.com/jupyter/nbdime#egg=nbdime and requires npm on the PATH.
Can nbdime merge notebooks automatically?
The README describes nbmerge as a three-way merge of notebooks with automatic conflict resolution, and nbmerge-web as a web-based three-way merge tool. A three-way merge needs a common ancestor, so the inputs are not just the two versions you want to combine.
Does nbdime work with git and Mercurial?
The repository topics list both git and mercurial alongside merge-driver and mergetool, and GitPython is a dependency with a comment tying it to the difftool taking git refs. The README itself points to the installation documentation for the configuration details rather than spelling out the flags.
What Python version does nbdime need?
pyproject.toml sets requires-python to >=3.10 and classifies the package for Python 3.10 through 3.14. The build backend is hatchling and the build requires jupyterlab 4.x.
What license does nbdime use?
The README states that all code is licensed under the terms of the revised BSD license, and pyproject.toml points the license field at LICENSE.md with a BSD classifier. The README also notes a shared copyright model where contributors keep copyright on their contributions.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jupyter-nbdime)