Okay, I am in the office. I am on the Mac. All that muscle memory stuff comes into effect. I have to do the real-time remapping sufficient so that flow state can still be achieved. Switching hardware, especially between different desktop OSes is very disruptive. But being able to do so is one of the most fundamental skills to future-proofing. They are trying to tie you to their particular hardware and OS, making switching hard.
It’s interesting that my first steps are now intuitively opening the terminal,
going to a repo, doing git pull and then nix develop
to ensure my nvim
environment is the same. This is a powerful technique to make muscle memory
portable. But it can’t do much about the host OS or the kooky key-swapping the
Mac does. Vim is an interoperable haven.
Okay, now focus on Notebook. I need to grab a code example from a notebook to
complete this, and I’m going to be doing a lot more Notebook work directly in
the Pipulate repo now in general. And I might be doing it from the Mac or my
NixOS machine at home. And I don’t want to pollute the Pipulate repo with
.ipynb
meta garbage, so it’s time to make sure nbstripout is working. I just
made a change to a notebook and did a git diff
and saw all the ugly cell
output! That’s a surprise because I thought I already had my favorite notebook
meta information scrubbing tool, nbstripout
turned on in the repo…
But it was using absolute paths, and switching between Linux and Mac made it
break, because my /home/user/
folder is different! On Mac it’s /Users/user/
And nbstripout
uses absolute paths in the repo’s .git/config
file.
Okay, if you’re here for the tool in the first place, this one is different from
the others because it’s (supposed to be) set-it and forget-it. Once you pip
install nbstripout
to get it on your machine, then you just cd
into your repo
and:
nbstripout --install --attributes .gitattributes
This ensures that nbstripout
works across different machines without absolute paths by using .gitattributes
instead of .git/config
.
Now, every time a Jupyter Notebook (.ipynb
) is committed, its output cells will be stripped automatically, keeping your repo clean across Mac, Linux, or any other environment you sync with.
Want to double-check if it’s working? Run:
git check-attr filter -- *.ipynb
It should return:
*.ipynb: filter: nbstripout
Then do another git diff
after modifying a notebook—you should no longer see output metadata polluting the diff.
This is the way to make nbstripout
truly cross-platform and set-it-and-forget-it. 🚀
Now just in case you happen to pull a repo that already has absolute paths in
its .git/config
like I just did, you can make sure your own global
configuration is clean and fix the repo by doing the following:
Step 1: Remove Absolute Paths from .git/config
If nbstripout
was previously installed with absolute paths, clean them out with:
git config --unset filter.nbstripout.clean
git config --unset filter.nbstripout.smudge
git config --unset filter.nbstripout.required
This ensures that the repo no longer has a broken absolute path reference.
Step 2: Enable Global nbstripout
(Optional)
If you want nbstripout
to work across all repos on your machine, install it globally:
nbstripout --install --global
This avoids repo-specific configuration issues.
Step 3: Ensure Portable .gitattributes
Usage
For maximum portability, ensure nbstripout
is applied using .gitattributes
instead:
nbstripout --install --attributes
This will create a .gitattributes
file containing:
*.ipynb filter=nbstripout
which is version-controlled and travels with the repo.
Step 4: Verify It’s Working
Test if nbstripout
is correctly applied:
git check-attr filter -- *.ipynb
It should return:
*.ipynb: filter: nbstripout
Then modify a notebook and run:
git diff
You should no longer see unwanted cell output in the diff.
Now, you’re fully future-proofed across Mac, NixOS, or any other machine you pull this repo on. 🚀
Double Checking WHY This Works
I confirmed that this works with a git diff, but I’m clarifying for myself double-checking with Gemini 2.5 exactly why this works.
Okay, let’s break down how the method described in the article avoids using absolute paths for nbstripout
:
- The Problem with the Old Method:
- The author initially had
nbstripout
configured directly within the repository’s local Git configuration file (.git/config
). - This configuration likely involved specifying the exact path to the
nbstripout
executable or related scripts. - These paths are absolute, meaning they start from the root directory of the filesystem (e.g.,
/Users/user/...
on Mac or/home/user/...
on Linux). - Because these paths are different on different operating systems (Mac vs. Linux), the configuration stored in
.git/config
would work on one machine but be broken on the other. The.git/config
file is specific to that local clone of the repository and isn’t typically shared or version-controlled.
- The author initially had
- The Solution Using
.gitattributes
:- The command
nbstripout --install --attributes
changes how Git is told to usenbstripout
. - Instead of putting absolute paths into the local
.git/config
, it modifies (or creates) a file named.gitattributes
directly within the repository. - Inside
.gitattributes
, it adds a line like:*.ipynb filter=nbstripout
- Crucially, this line does not contain an absolute path. It simply tells Git: “For any file ending in
.ipynb
, apply a filter namednbstripout
.”
- The command
- How Git Finds
nbstripout
:- The
.gitattributes
file tells Git which filter to use (by name: “nbstripout”), but not where that filter command is located. - Git finds the actual command for the “nbstripout” filter by looking in its configuration (often set up globally or locally by running
nbstripout --install
ornbstripout --install --global
previously). - This setup relies on the
nbstripout
command being available in the system’sPATH
on whatever machine you are currently using. - When you run a Git command (like
git commit
orgit diff
), Git sees the instruction in.gitattributes
, looks up the “nbstripout” filter definition, finds thenbstripout
command in the current system’sPATH
, and executes it.
- The
- Why This is Portable:
- The
.gitattributes
file is part of the repository and is version-controlled, so it’s identical on every machine (Mac, Linux, etc.) that clones the repo. - It contains only the name of the filter, not a system-specific path.
- The responsibility of finding the
nbstripout
executable is shifted to the Git installation on the local machine, which uses the local system’sPATH
. - As long as
nbstripout
is installed and accessible on each machine you work on, Git can find and run it correctly using the portable instructions from.gitattributes
.
- The
In essence, the .gitattributes
file provides a portable, repository-level instruction (“use the nbstripout filter”), while the actual execution relies on the nbstripout
tool being correctly installed and findable on the specific machine where the Git commands are being run, thus avoiding hardcoded, OS-dependent absolute paths within the shared repository configuration.
An AI’s Summary
Here’s the summary from the author’s perspective:
[Moved to top]
Title/Headline Ideas:
- Make
nbstripout
Truly Cross-Platform with.gitattributes
- Solving
nbstripout
Absolute Path Issues Between Mac and Linux - Set-and-Forget Jupyter Notebook Cleaning in Git Across Any OS
- Portable
nbstripout
: Stop Committing Notebook Output Metadata - Fixing Broken
nbstripout
Configs for Multi-OS Development - Keep Your Jupyter Notebook Diffs Clean Everywhere with
nbstripout
and.gitattributes
- The Right Way to Install
nbstripout
for Cross-Platform Repos
AI Opinion:
This article provides a practical and valuable solution to a common frustration
for developers working with Jupyter Notebooks in Git repositories across
different operating systems (like macOS and Linux). The author effectively uses
a personal narrative about switching machines to frame the technical problem –
nbstripout
failing due to absolute path configurations in .git/config
. The
explanation of why this happens and the clear, step-by-step instructions on
using .gitattributes
for a portable, repository-level solution are excellent.
Including commands for verification and troubleshooting existing configurations
adds significant utility. It’s a well-focused piece that directly addresses a
specific technical pain point with an actionable fix.