Guida

File .gitignore: come escludere i file da Git e rimuovere quelli già aggiunti

Aggiornato: · Skillaria.Top

Il file .gitignore nella radice del repository elenca i modelli di file e cartelle che Git non tracerà: dipendenze, build, log, segreti. Vale solo per i file non tracciati, quindi un file già committato va tolto dall'indice con git rm --cached.

Il meccanismo di gitignore serve a dire a Git: «questi file non toccarli, non mostrarli in git status e non aggiungerli con git add .». Le regole si scrivono in un file di testo chiamato .gitignore, che viene committato insieme al progetto e vale per tutto il team. La sottigliezza principale: il file di esclusione agisce solo sui file che Git non traccia ancora.

Che cosa si aggiunge di solito a .gitignore

  • Dipendenze: node_modules/, vendor/, .venv/ — le ripristina il gestore dei pacchetti.
  • Risultati della build: dist/, build/, *.class, __pycache__/.
  • Log e file temporanei: *.log, tmp/, *.swp.
  • Segreti e impostazioni locali: .env, chiavi, configurazioni locali.
  • Rifiuti di sistema e dell'editor: .DS_Store, Thumbs.db, .idea/ — meglio però tenerli nel gitignore globale, di cui parliamo più avanti.

La regola è semplice: nel repository deve finire ciò che scrivono le persone, non ciò che generano i programmi o che dipende dalla singola macchina.

Come creare un .gitignore

È un normale file di testo nella radice del repository. Createlo, scrivete i modelli uno per riga e committatelo:

cat > .gitignore <<'EOF'
# dipendenze
node_modules/
# build
dist/
# log
*.log
# segreti
.env
EOF

git add .gitignore
git commit -m "chore: aggiunto .gitignore"

Modelli pronti per i linguaggi e i framework più diffusi si trovano nel repository github/gitignore; GitHub e GitLab propongono di sceglierne uno quando create il progetto. Usatelo come base e togliete ciò che non serve.

Sintassi dei modelli .gitignore

ModelloChe cosa ignora
*.logtutti i file con estensione .log in qualsiasi cartella
build/la cartella build a qualsiasi livello (la barra finale indica solo le cartelle)
/buildsolo build nella radice (la barra iniziale lega il modello alla cartella del .gitignore)
docs/*.pdfi pdf direttamente in docs, ma non in docs/old/
docs/**/*.pdfi pdf in docs e in tutte le sottocartelle
**/temptemp in qualsiasi cartella
!keep.logeccezione: non ignorare keep.log
file?.txt? — un carattere qualsiasi
[ab].txta.txt oppure b.txt
# commentoriga di commento

Dettaglio importante: un modello senza barra all'interno (config.json) vale a qualsiasi livello, mentre un modello con una barra all'inizio o nel mezzo (/config.json, src/config.json) è riferito alla cartella in cui si trova questo .gitignore.

Eccezioni con il punto esclamativo

*.log
!important.log

Trappola: non si può «riabilitare» un file se è ignorata la sua cartella madre. Git non entra nelle cartelle ignorate, quindi questo non funziona:

logs/
!logs/keep.txt     # non funziona

Il modo giusto è ignorare il contenuto, non la cartella:

logs/*
!logs/keep.txt

Lo stesso trucco serve a conservare una cartella vuota nel repository: Git non memorizza le cartelle vuote, quindi si mette dentro un file .gitkeep e si consente solo quello.

Dove altro si può impostare l'esclusione

PosizioneVale perFinisce nel repository
.gitignore nella radice e nelle sottocartelletutto il teamsì
.git/info/excludesolo questo cloneno
file globale indicato in core.excludesFiletutti i vostri repositoryno

I rifiuti del vostro sistema operativo e dell'IDE conviene metterli nel gitignore globale, per non sporcare quello condiviso:

git config --global core.excludesFile ~/.gitignore_global
echo ".DS_Store" >> ~/.gitignore_global
echo ".idea/" >> ~/.gitignore_global

Se core.excludesFile non è impostato, Git legge ~/.config/git/ignore, se esiste.

Perché .gitignore non funziona

La lamentela più frequente è: «ho aggiunto il file a .gitignore, ma Git mostra ancora le modifiche». La causa è quasi sempre una sola: il file è già tracciato. L'esclusione non ha effetto sui file che sono finiti in un commit.

Per capire quale regola si applica (o perché non si applica) serve git check-ignore:

git check-ignore -v logs/app.log
# .gitignore:3:*.log	logs/app.log

L'output indica il file e la riga della regola. Un output vuoto significa che il file non è ignorato. Un'altra causa di problemi sono gli spazi alla fine di una riga del modello o una codifica sbagliata del file (per esempio UTF-16, se creato con PowerShell).

Come togliere dal repository un file già committato: git rm --cached

Il comando git rm rimuove il file dall'indice e dal disco. Con il flag --cached lo rimuove solo dall'indice: il file resta sul vostro computer, ma smette di essere tracciato.

echo ".env" >> .gitignore
git rm --cached .env
git commit -m "chore: .env non è più tracciato"
git push

Per una cartella serve -r:

git rm -r --cached node_modules/

Se le regole sono molte e non è chiaro che cosa sia già finito nel repository, si può ricostruire l'indice da zero: git rm -r --cached ., poi git add . e il commit. Prima di committare controllate git status: vi compariranno i file tolti dall'indice.

Attenzione: i segreti restano nella cronologia

git rm --cached toglie il file dai commit successivi, ma non da quelli precedenti. Se nel repository è finita una password o un token, è accessibile nella cronologia a chiunque abbia un clone. Il segreto va considerato compromesso e rigenerato. La cronologia si può riscrivere con strumenti come git filter-repo, ma così cambiano gli hash di tutti i commit successivi e bisogna concordarlo con il team.

Un'altra conseguenza: ai colleghi, dopo un git pull, un file tolto dall'indice con --cached verrà eliminato dal disco. Per il file .env avvisate il team in anticipo oppure tenete nel repository un modello .env.example.

git rm: eliminare i file

git rm old.py              # elimina dal disco e dall'indice
git rm -r legacy/          # elimina una cartella
git rm -n '*.tmp'          # dry run: mostra che cosa verrebbe eliminato
git rm -f changed.py       # elimina un file con modifiche non committate

Se eliminate un file con il normale rm, Git lo vede come «deleted» e la cancellazione va aggiunta con git add o git rm. git rm fa entrambi i passi in un colpo solo. Senza -f rifiuta di eliminare un file con modifiche non committate: è una protezione contro la perdita di lavoro.

git mv: rinominare e spostare

git mv utils.py helpers.py
git mv helpers.py src/helpers.py

git mv è l'abbreviazione di mv + git rm del vecchio percorso + git add del nuovo. Git non memorizza il fatto che un file è stato rinominato: lo deduce dalla somiglianza del contenuto quando mostra git status, git log --follow o git diff. Quindi rinominare con git mv oppure con il normale mv seguito da git add -A dà lo stesso risultato.

Consiglio pratico: rinominate e modificate il contenuto del file in commit diversi. Se il file cambia molto insieme al nome, Git potrebbe non riconoscerlo come lo stesso file e la cronologia con --follow si interrompe.

Per cambiare solo le maiuscole/minuscole del nome su Windows e macOS (i file system non distinguono le maiuscole) usate git mv readme.md README.md: una semplice rinomina in Esplora risorse potrebbe non essere notata da Git.

Ordine delle regole e priorità

All'interno di un file le regole si leggono dall'alto verso il basso e vince l'ultima che corrisponde. Per questo l'eccezione !keep.log deve stare sotto la regola *.log, altrimenti viene coperta. Tra file diversi la priorità è questa: il .gitignore di una sottocartella prevale su quello della radice, mentre il gitignore globale e .git/info/exclude hanno la priorità più bassa.

Esempio di .gitignore per un progetto web

Ecco una versione funzionante per un progetto con Node.js e un backend in Python. Leggete i commenti: tra sei mesi nessuno ricorderà perché è stata aggiunta una certa regola.

# --- dipendenze ---
node_modules/
.venv/

# --- build e cache ---
/dist
/build
__pycache__/
*.pyc
.pytest_cache/
coverage/

# --- log ---
*.log
npm-debug.log*

# --- ambiente e segreti ---
.env
.env.*
!.env.example

# --- upload degli utenti: la cartella resta, il contenuto no ---
uploads/*
!uploads/.gitkeep

Qui si usano entrambi i trucchi con le eccezioni: .env.* nasconde tutte le varianti locali dell'ambiente, ma il modello .env.example resta nel repository; la cartella uploads esiste nel clone grazie al file .gitkeep.

Che cosa non conviene ignorare

Anche esagerare con le esclusioni fa male. I file di lock delle dipendenze — package-lock.json, poetry.lock, composer.lock — nelle applicazioni si committano di solito: garantiscono che tutti gli sviluppatori e il CI installino le stesse versioni dei pacchetti. Anche le impostazioni di formattazione condivise (.editorconfig, configurazioni dei linter) devono stare nel repository.

Caso controverso: le impostazioni dell'IDE. La cartella .vscode/ viene spesso ignorata per intero, ma a volte si committano le estensioni consigliate e le attività di build: .vscode/*, poi !.vscode/extensions.json. La decisione spetta al team; l'importante è non mettere nel repository condiviso percorsi personali e chiavi.

Scenario: avete committato node_modules per errore

Errore classico di chi comincia: git add . prima di creare il .gitignore, e nel commit finiscono decine di migliaia di file. La correzione in tre passi:

echo "node_modules/" >> .gitignore
git rm -r --cached node_modules
git commit -m "chore: node_modules rimosso dal repository"

Se il commit non è ancora stato inviato al server, conviene riscriverlo per non lasciare i file pesanti nella cronologia: git reset --soft HEAD~1, poi gli stessi comandi e un nuovo commit. Dopo il push i file sono già nella cronologia, e la dimensione del clone non diminuirà senza riscrivere la storia.

Per non ripetere l'errore, create il .gitignore prima del primo git add e abituatevi a guardare git status prima di committare: un elenco di nuovi file sospettosamente lungo è il motivo per fermarsi.

Il file .gitignore è il primo file da committare in un progetto nuovo: dipendenze, build, log e segreti non devono stare nel repository. L'esclusione funziona solo sui file non tracciati, quindi quelli già aggiunti si tolgono con git rm --cached, e le regole si verificano con git check-ignore -v. Per eliminare e rinominare usate git rm e git mv, così le modifiche entrano subito nell'indice. Il lavoro con l'indice e il primo repository lo analizziamo in pratica nel corso di Git.

Domande frequenti

Bisogna committare anche il file .gitignore?

Sì, così le regole valgono per tutto il team; le esclusioni personali mettetele in .git/info/exclude oppure nel gitignore globale.

Si possono avere più file .gitignore?

Sì, il file può stare in qualsiasi sottocartella e le sue regole valgono rispetto a quella cartella, integrando quelle della radice.

Come si aggiunge al commit un file ignorato?

Usate git add -f percorso/del/file; dopo questo il file è tracciato e .gitignore non lo riguarda più.

Come vedere tutti i file ignorati del progetto?

Eseguite git status --ignored oppure git ls-files --others --ignored --exclude-standard.

Come smettere temporaneamente di tracciare modifiche a un file già committato?

Esiste git update-index --skip-worktree file, ma è un'impostazione locale e non sostituisce .gitignore.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Git da zero a sviluppatore sicuro».

Vai al corso