A complete Python .gitignore
Python projects generate plenty of files you never want in version control: bytecode caches, virtual environments, packaging artifacts, and test coverage data. This builder produces a clean .gitignore for Python repositories, with each section toggleable so the file matches your exact toolchain.
The unique challenge of Python ignores
Python’s file generation is distributed across multiple tools — the interpreter itself, packaging tools (setuptools, build, flit, poetry), test runners (pytest, tox), type checkers (mypy, pyright, ruff), and IDEs. Each generates its own cache or output directory. Unlike a compiled language where everything goes into a single build/ directory, Python artifacts scatter across the project tree. A thorough .gitignore needs to know which tools you use.
How Git applies the patterns
Git evaluates each line as a pattern relative to the repository root. Key rules:
- A bare name like
venvmatches a file or directory with that name anywhere in the tree - A trailing slash like
venv/matches only directories - A glob like
*.pycmatches by extension anywhere in the tree - A leading
/like/.envrestricts the match to the repository root only - Patterns are additive — each section’s patterns append to the overall ignore list
Section-by-section breakdown
Byte-compiled files — Python automatically creates .pyc and .pyo bytecode files alongside your source, collected under __pycache__/ directories in Python 3. The pattern *.py[cod] catches .pyc, .pyo, and .pyd in one line.
Virtual environments — venv/, .venv/, env/, .env/ are the common names for isolated Python environments. The directory contains a full Python install and all your installed packages; it is large (often hundreds of MB), platform-specific, and entirely reproducible from your dependency file. Never commit it.
Environment files (.env) — .env stores environment variables, commonly including database credentials, API keys, and secret tokens. It should never be committed. Keep a sanitised .env.example with placeholder values in the repo instead.
Packaging output — build/, dist/, *.egg-info/, .eggs/ are generated by python -m build, setuptools, and pip install -e .. They contain compiled wheels and distribution archives — derived artifacts that are uploaded to PyPI, not stored in the repository.
Testing caches — .pytest_cache/ is pytest’s internal cache for last-run results and the --lf (last-failed) feature. .coverage is the raw coverage data file generated by pytest-cov or coverage run. htmlcov/ is the rendered HTML coverage report. .tox/ holds tox’s virtualenv matrix. All are regenerable and should not be committed.
Type checker caches — .mypy_cache/ and .ruff_cache/ store cached analysis results that speed up repeated runs. These are local and machine-specific.
IDE folders — .vscode/ and .idea/ store editor settings. Some teams commit a subset (e.g. a shared .vscode/launch.json), but the default is to ignore the whole directory and let each developer configure their editor locally.
What you should always commit
requirements.txt,requirements-dev.txt,pyproject.toml,poetry.lock, orPipfile.lock— your dependency manifest, not the installed packagessetup.pyorsetup.cfg— project metadata.env.example— a sanitised template showing which variables the project needs
Recovering from an already-tracked file
If __pycache__ or another artifact was committed before this file was added, .gitignore alone won’t stop Git tracking it. Run:
git rm -r --cached __pycache__
git commit -m "stop tracking __pycache__"
This removes the directory from the index without deleting it locally, after which the .gitignore pattern takes effect.