Session 6 · Ways to exclude files#
The big idea#
Some files should never go into a repository: passwords, logs, build output, editor settings, the
node_modules folder. A .gitignore file lists patterns for files Git should pretend not to see.
Ignored files do not show in git status and git add . skips them.
Everyday example: the “do not photocopy” tray at an office. Confidential papers, rough drafts and the tea-stained scribbles go in it. When someone says “copy everything on my desk”, the clerk skips that tray.
Ignore rules at work#
git config --global user.name "Dev User"
git config --global user.email "dev@example.com"
git config --global init.defaultBranch main
git init -q shop
cd shop
touch app.py secrets.env debug.log error.log notes.txt important.txt
mkdir build && touch build/out.bin
echo '--- before .gitignore: everything is untracked'
git status -s
printf '%s\n' '# secrets' 'secrets.env' '' '# logs' '*.log' '' '# build output' 'build/' '' '# all text files, except one' '*.txt' '!important.txt' > .gitignore
echo '--- after .gitignore'
git status -s
echo '--- why is a file ignored? (-v shows the rule)'
git check-ignore -v debug.log build/out.bin notes.txt
echo '--- is important.txt ignored? (exit code 1 = no)'
git check-ignore important.txt; echo "exit code $?"
echo '--- files you can see in the folder but Git skips'
git status --ignored -s | grep '^!!'
echo '--- an ignore rule only affects UNTRACKED files'
git add -f secrets.env
git commit -q -m "Oops, committed secrets"
echo "password=123" >> secrets.env
git status -s
echo '--- fix: stop tracking it, keep the file on disk'
git rm -q --cached secrets.env
git commit -q -m "Stop tracking secrets.env"
git status -s
echo '--- a private rule for this clone only (never committed)'
echo "scratch/" >> .git/info/exclude
mkdir scratch && touch scratch/ideas.txt
git status -s
--- before .gitignore: everything is untracked
?? app.py
?? build/
?? debug.log
?? error.log
?? important.txt
?? notes.txt
?? secrets.env
--- after .gitignore
?? .gitignore
?? app.py
?? important.txt
--- why is a file ignored? (-v shows the rule)
.gitignore:5:*.log debug.log
.gitignore:8:build/ build/out.bin
.gitignore:11:*.txt notes.txt
--- is important.txt ignored? (exit code 1 = no)
exit code 1
--- files you can see in the folder but Git skips
!! build/
!! debug.log
!! error.log
!! notes.txt
!! secrets.env
--- an ignore rule only affects UNTRACKED files
M secrets.env
?? .gitignore
?? app.py
?? important.txt
--- fix: stop tracking it, keep the file on disk
?? .gitignore
?? app.py
?? important.txt
--- a private rule for this clone only (never committed)
?? .gitignore
?? app.py
?? important.txt
Reading the output:
Before
.gitignoreseven things appear as untracked, includingsecrets.envand thebuild/folder.After, only
.gitignore,app.pyandimportant.txtremain.important.txtsurvived thanks to the negation rule!important.txt, which re-includes a file that*.txtwould have ignored.git check-ignore -vtells you which rule in which line ignores a file, the quickest way to debug a pattern. Forimportant.txtit printed nothing and exit code 1, meaning “not ignored”.git status --ignoredlists the ignored files (marked!!) in case you want to see them.The
secrets.envtrap. We force-added it and committed, and then ignore rules stopped working for it: editing it showedM secrets.env. An ignore rule only affects untracked files.git rm --cachedremoved it from Git’s tracking but kept the file on disk; after that it is ignored again. (If a secret was already pushed, assume it is public: change the password. Removing it from history is a separate, harder job.).git/info/excludeworks like.gitignorebut is private to your clone and is never committed. Thescratch/folder is hidden fromgit statuswithout touching the shared file.
Pattern cheat sheet#
Pattern |
Matches |
|---|---|
|
Any file ending in |
|
The folder |
|
Only |
|
Re-include a file an earlier rule ignored |
|
PDFs anywhere under |
|
A comment line |
Three places for rules: the project’s .gitignore (shared with the team, committed), .git/info/exclude
(just you, this clone) and a global file (git config --global core.excludesFile ~/.gitignore_global) for things
like .DS_Store that you never want in any repository.
Other ways to leave files out of one commit#
git add -- ':!README.md'skips a file for thisaddonly (Session 5).git restore --staged FILEtakes it back out of the staging area.git update-index --skip-worktree FILEasks Git to stop noticing local edits to a tracked file, handy for a personal copy of a config file. Undo with--no-skip-worktree.
Common mistakes#
Adding the pattern after the file is committed. It has no effect; use
git rm --cachedas shown.Ignoring
.gitignoreitself. You want it committed so teammates get the same rules.Expecting
*.txtto be re-included by a later!fileinside an ignored folder. If a folder is ignored, Git never looks inside it, so a negation for a file inside will not work.Committing secrets “just once”. Once pushed, treat the secret as leaked.
Writing
buildwhen you meanbuild/. Without the slash it also matches a file calledbuild.
Hands-on exercises#
Exercise 1. Ignore all .log files and the dist/ folder. Prove it with git check-ignore -v.
Solution
printf '*.log\ndist/\n' > .gitignore
touch app.log && mkdir dist && touch dist/bundle.js
git check-ignore -v app.log dist/bundle.js
It prints the rule and line for each: .gitignore:1:*.log app.log and .gitignore:2:dist/ dist/bundle.js.
Exercise 2. Ignore every .txt file except keep.txt.
Solution
printf '*.txt\n!keep.txt\n' > .gitignore
touch a.txt keep.txt
git status -s
a.txt is hidden; keep.txt (and .gitignore) show as ??.
Exercise 3. You committed .env by mistake. Stop tracking it but keep it on your disk.
Solution
echo ".env" >> .gitignore
git rm --cached .env
git add .gitignore
git commit -m "Stop tracking .env"
The file remains in the folder, is ignored from now on, and the commit removes it from the project going forward. If it contained a real password, change that password, because it is still in the earlier history.
Practice#
Take the Session 6 quiz. The original Ways to Exclude Files in Git page is in the reference section.