What Is .ipynb_checkpoints? Deleting It, and the Git Commands That Actually Untrack It
What Is .ipynb_checkpoints?
The .ipynb_checkpoints folder is a hidden directory that Jupyter Notebook creates automatically next to your .ipynb files. It stores checkpoint snapshots that let you revert to a previous saved state. These folders are safe to delete and should be added to .gitignore to keep your repositories clean.
If the rule is already in .gitignore and Git still shows the files, that is expected
behaviour rather than a bug, and the fix is not another ignore pattern. Skip to
Already committed? .gitignore will not help,
which walks a throwaway repository through what each untracking command does to your index.
TL;DR
- Jupyter creates a hidden folder named
.ipynb_checkpointsnext to your notebooks. - Inside it are snapshot files like
MyNotebook-checkpoint.ipynbthat let you revert to a prior state. - They’re safe to delete, but you’ll lose the quick local rollback for that notebook.
- Add them to
.gitignore,.dockerignore, and clean them in CI to avoid repo bloat.
What is .ipynb_checkpoints?
When you open and save a Jupyter Notebook, Jupyter keeps lightweight snapshots (checkpoints) of your work. These are stored in a hidden directory named .ipynb_checkpoints in the same folder as your notebook(s).
A typical structure looks like this:
project/
├─ data/
├─ analysis/
│ ├─ exploration.ipynb
│ ├─ model.ipynb
│ └─ .ipynb_checkpoints/
│ ├─ exploration-checkpoint.ipynb
│ └─ model-checkpoint.ipynb
└─ README.mdEach *-checkpoint.ipynb is a JSON notebook file, just like your main .ipynb, but captured at a previous point in time.
Are checkpoints the same as autosave?
Not exactly.
- Autosave updates your main
.ipynbfile at an interval (and on explicit save). - Checkpoints are separate snapshots saved in
.ipynb_checkpointsthat you can revert to from the UI.
Front‑end behavior varies slightly:
- Classic Notebook exposes “Save and Checkpoint” and “Revert to Checkpoint.”
- JupyterLab provides “Revert Notebook to Checkpoint” in the File menu and keeps autosave configurable.
- Some alternative front‑ends (e.g., VS Code’s Jupyter integration) may not create
.ipynb_checkpointsbut will happily open notebooks that have them.
Why do they keep reappearing?
Because they’re part of Jupyter’s safety net. Even if you delete the folder, Jupyter will recreate it the next time it saves a checkpoint for that directory. That’s by design.
Is it safe to delete them?
Yes. Deleting .ipynb_checkpoints does not remove your main notebook; it only removes the snapshots. You’ll lose the quick “revert” option for those notebooks until new checkpoints are created.
Good times to delete:
- Before publishing or sharing a project archive.
- During CI or image builds to reduce size/noise.
- When a checkpoint captured sensitive output you don’t want distributed.
Keep them out of Git (and friends)
Checkpoints don’t belong in version control—Git already provides version history. Add these rules to your ignore files:
.gitignore
# Jupyter Notebook checkpoints
.ipynb_checkpoints/
**/.ipynb_checkpoints/
*-checkpoint.ipynb.dockerignore
.ipynb_checkpoints/
**/.ipynb_checkpoints/
*-checkpoint.ipynbThe double‑star ensures nested directories are covered. The file pattern is a belt‑and‑suspenders to catch any stray checkpoint files that may have been copied out of the folder.
If you use pre‑commit, you can also enforce cleanup:
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: clean-ipynb-checkpoints
name: Remove Jupyter checkpoints
language: system
pass_filenames: false
entry: bash -c 'find . -name "*-checkpoint.ipynb" -delete && find . -type d -name ".ipynb_checkpoints" -empty -delete'Already committed? .gitignore will not help
This is the most common .ipynb_checkpoints problem, and the cause is a Git rule with
nothing to do with Jupyter: .gitignore applies to untracked paths only. Once a file
is in the index, Git keeps tracking it whatever the ignore rules say.
Everything below came from a script run against Git 2.50.1 (Apple Git-155). It builds a
throwaway repository in a temp directory (three files, one of them a checkpoint committed
by mistake), then tries each fix in turn. The blocks are pasted as they came out; the
== headings are the script’s own.
Step 1 - the mistake
== 1. what is tracked before we do anything ==
analysis/.ipynb_checkpoints/model-checkpoint.ipynb
analysis/model.ipynb
train.pyStep 2 - adding the ignore rule changes nothing
== 2. add the ignore rule, then check again ==
.gitignore
analysis/.ipynb_checkpoints/model-checkpoint.ipynb
analysis/model.ipynb
train.pyThe checkpoint is still in git ls-files. It is not dormant either - edit it and Git
notices at once:
== 3. prove it is still live: edit it and see Git notice ==
M analysis/.ipynb_checkpoints/model-checkpoint.ipynbStep 3 - the targeted fix
Untrack the checkpoints and nothing else:
git rm -r --cached --ignore-unmatch '*.ipynb_checkpoints/*'
git commit -m "Stop tracking Jupyter checkpoints"== 5. the targeted command, from a clean index ==
.gitignore
analysis/.ipynb_checkpoints/model-checkpoint.ipynb
analysis/model.ipynb
train.py
-- run it --
-- files left in the index --
.gitignore
analysis/model.ipynb
train.py
-- git status --short --
D analysis/.ipynb_checkpoints/model-checkpoint.ipynbOne staged deletion, nothing else touched. --cached means the index only, so the file
stays on disk; the script’s last step confirms model-checkpoint.ipynb is still there
after the commit. --ignore-unmatch stops the command failing on a repository that has no
checkpoints, which matters if it lives in a script.
Step 4 - the broad recipe, and the state it passes through
The widely repeated version is git rm -r --cached . then git add .. It works, and
it is the right tool when you have just added several ignore rules at once. It is still
worth seeing the index between the two commands:
== 4. what 'git rm -r --cached .' does to the index ==
-- files left in the index --
(empty: the index now lists nothing. Every path has a STAGED DELETION,
and its working-tree copy shows up as untracked -- see status below.)
-- git status --short --
D .gitignore
D analysis/.ipynb_checkpoints/model-checkpoint.ipynb
D analysis/model.ipynb
D train.py
?? .gitignore
?? analysis/
?? train.pyEvery tracked path is staged for deletion. Committing at that point - an interrupted
terminal, a reflexive git commit -am, a script that does not stop on error - commits the
removal of the whole repository. git add . restores it correctly:
== 4b. the same recipe finished properly: git add . after it ==
-- files left in the index --
.gitignore
analysis/model.ipynb
train.py
-- git status --short --
D analysis/.ipynb_checkpoints/model-checkpoint.ipynbSame end state as the targeted command. What differs is the blast radius on the way there, and that the resulting diff touches every path your ignore rules now cover rather than only the checkpoints.
Prefer the targeted command unless you specifically want to re-apply every ignore rule in the repository at once.
What neither command does
Untracking keeps the file out of future commits. It does not remove it from history:
whatever a checkpoint captured is still in earlier commits and still reachable. If one
recorded a token or customer data, untracking is not the remedy - rewriting history with
git filter-repo and rotating the secret is.
Clean up checkpoints safely
Linux/macOS (bash)
Delete only checkpoint files:
find . -name "*-checkpoint.ipynb" -deleteRemove empty .ipynb_checkpoints folders afterward:
find . -type d -name ".ipynb_checkpoints" -empty -deleteWindows (PowerShell)
Get-ChildItem -Recurse -Filter *-checkpoint.ipynb | Remove-Item
Get-ChildItem -Recurse -Directory -Filter .ipynb_checkpoints | Remove-Item -Recurse -ForceTip: Prefer deleting files first, then removing now‑empty directories. This minimizes the chance of deleting unrelated content if paths were nested in unexpected ways.
Reverting to a checkpoint
If you haven’t deleted them yet:
- JupyterLab:
File → Revert Notebook to Checkpoint→ pick the desired snapshot. - Classic Notebook:
File → Revert to Checkpoint→ choose from the list.
If the option is disabled or empty, there are no checkpoints yet for that notebook.
Autosave and configuration tips
- Autosave interval is configurable in JupyterLab (
Settings → Advanced Settings Editor → Notebook → autosaveIntervalin milliseconds). A shorter interval reduces data‑loss risk but may write more frequently. - If you turn off autosave, manual saves will still create/update checkpoints in many front‑ends. Expect
.ipynb_checkpointsto show up again when you save.
There isn’t a universally supported, single “disable checkpoints forever” switch. The safest pattern is to ignore and clean them rather than trying to disable the mechanism.
CI/CD & packaging
- GitHub Actions / CI: Add the cleanup commands as a step before caching artifacts or publishing wheels/docs.
- Docker images: Use
.dockerignoreto prevent copying checkpoints into build context; if already copied, delete them in a build stage. - Archives/exports: Run cleanup before zipping or releasing datasets/notebooks to avoid leaking large outputs or sensitive cells captured in a checkpoint.
Security & privacy notes
- Checkpoints may contain cell outputs (e.g., partial results, printed secrets) that existed when the snapshot was taken.
- If you’re publishing a public repo, treat checkpoints as sensitive: ensure they are ignored, or explicitly cleaned.
FAQ
Q: My repo keeps showing new *-checkpoint.ipynb files even with .gitignore. Why?
A: They were committed before the ignore rule existed, and .gitignore has no effect on
files Git already tracks. See
Already committed? .gitignore will not help
for the two commands that fix it, and what each does to the rest of your index.
Q: Can I use checkpoints as ‘real’ versioning?
A: They’re best for local, short‑term rollback, not for collaboration history. Use Git (optionally with tools like nbdime) for meaningful diffs and merges.
Q: Do other notebook tools create the same folder? A: Not all. Behavior depends on the front‑end. Jupyter’s classic UI and JupyterLab commonly do; others may rely on different backup systems.
Recommended defaults
- Keep checkpoints enabled (they’re handy).
- Ignore them in VCS and build contexts.
- Clean them in CI and before publishing.
That balance gives you fast local safety with clean, lightweight repositories.
Before you export or share a notebook
Clearing checkpoints is usually one step of a larger “make this notebook presentable” job. Two things worth doing in the same pass:
- Convert the notebook, not one of its snapshots. A stale
-checkpoint.ipynbnext to the real file is easy to hand to a converter by accident. For a single notebook, the notebook-to-PDF converter and the notebook-to-HTML converter take the file you pick and nothing else. - Know what the export will drop. PDF conversion is lossy in ways that are not obvious: a measured fidelity benchmark found the LaTeX route removing some non-ASCII characters without reporting a failure, and the browser routes dropping most of a 24-column DataFrame off the page edge.