Ignore everything except selected files in Git
Build a .gitignore allowlist with negated patterns, re-include parent directories, and check which rule controls a path.
Start with * to ignore untracked paths, then use patterns beginning with ! to keep selected files visible to Git. For nested files, also re-include each parent directory. Git does not search an excluded directory for possible exceptions inside it.
These rules affect untracked files. They do not remove files that are already tracked.
Keep a few root files and an entire source tree
In the repository's root .gitignore:
# Ignore by default.
*
# Keep these root files.
!/.gitignore
!/README.md
!/Makefile
# Keep the source directory and its descendants.
!/src/
!/src/**
The leading slash anchors these exceptions to the directory containing this .gitignore. The explicit directory exception lets Git enter src/; the recursive exception permits its contents.
Keep one nested file
For a root docs/guide.pdf, use:
*
!/.gitignore
!/docs/
/docs/*
!/docs/guide.pdf
For a deeper file, open the parent chain as well:
*
!/.gitignore
!/docs/
/docs/*
!/docs/manual/
/docs/manual/*
!/docs/manual/guide.pdf
Put comments on separate lines. A trailing # explanation is part of a .gitignore pattern, not a shell-style comment.
If you want every descendant of docs/, use !/docs/ followed by !/docs/**. A recursive file exception alone does not overcome an excluded parent.
Check the rule that applies
git check-ignore -v -- docs/guide.pdf
git status --ignored
Verbose check-ignore can print a matching negated rule, so output does not automatically mean the file is ignored. Read the pattern: a leading ! marks an exception. Ordinary tracked files are omitted from this check by default; use --no-index when diagnosing which ignore rules would match one:
git check-ignore -v --no-index -- docs/guide.pdf
Finally, use git status --short --untracked-files=all to verify the paths you expect to add.
FAQ
Why does !file.txt do nothing?
A parent directory may still be excluded. Re-include every required parent and place the exception after the rule it overrides. The applicable rule's location and precedence also matter when several ignore files exist.
When is an allowlist useful?
It can suit a minimal example repository or a directory where only selected release artifacts should be tracked. For everyday development, ignoring known generated files is often easier to maintain because new source files remain visible by default.
Can I preserve logs/.gitkeep while excluding logs?
Yes, keep the directory traversable and allow only the placeholder:
*
!/.gitignore
!/logs/
/logs/*
!/logs/.gitkeep
The placeholder is an ordinary tracked file; its name does not override ignore rules on its own.
See gitignore and git-check-ignore.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan