Git vede tutti i file nella copia di lavoro in uno di questi tre stati:

  1. monitorato: un file che è stato precedentemente preparato per il commit o sottoposto a commit;
  2. non monitorato: un file che non è stato preparato per il commit o sottoposto a commit; oppure
  3. ignorato: un file per cui Git ha ricevuto l'istruzione esplicita di ignorare.

I file ignorati sono in genere artefatti di build e file generati dal computer che possono derivare dall'origine del repository o che non devono essere sottoposti a commit. Alcuni esempi comuni sono:

  • cache delle dipendenze, come i contenuti di /node_modules o /packages;
  • codice compilato, ad esempio i file .o, .pyc e .class;
  • directory di output della build, ad esempio /bin, /out o /target;
  • file generati in fase di esecuzione, ad esempio .log, .lock o .tmp;
  • file di sistema nascosti, ad esempio .DS_Store o Thumbs.db;
  • file di configurazione IDE personali, ad esempio .idea/workspace.xml.

I file ignorati vengono monitorati in un file speciale denominato .gitignore, archiviato nella directory principale del repository. Non esiste un comando git ignore esplicito: il file .gitignore deve essere modificato e sottoposto a commit manuale se sono presenti nuovi file che si desidera ignorare. I file .gitignore contengono schemi che vengono confrontati con i nomi dei file nel repository per determinare se devono essere ignorati o meno.

Schemi di git ignore

.gitignore utilizza schemi di glob da confrontare con i nomi dei file. Puoi costruire gli schemi usando vari simboli:

Schema Corrispondenze di esempio Spiegazione*
**/logs logs/debug.log
logs/monday/foo.bar
build/logs/debug.log
È possibile anteporre uno schema con un doppio asterisco per cercare le directory in qualsiasi punto del repository.
**/logs/debug.log logs/debug.log
build/logs/debug.log
ma non
logs/build/debug.log
Puoi usare un doppio asterisco anche per cercare i file in base al loro nome e a quello della relativa directory principale.
*.log debug.log
foo.log
.log
logs/debug.log
Un asterisco è un carattere jolly che corrisponde a zero o più caratteri.
*.log
!important.log
debug.log
trace.log
ma non
important.log
logs/important.log
Se viene anteposto un punto esclamativo a uno schema, quest'ultimo viene negato. Se un file corrisponde a uno schema, ma anche a uno schema di negazione definito più avanti nel file, non verrà ignorato.
*.log
!important/*.log
trace.*
debug.log
important/trace.log
ma non
important/debug.log
Gli schemi definiti dopo uno schema di negazione ignoreranno nuovamente tutti i file precedentemente negati.
/debug.log debug.log
ma non
logs/debug.log
Se viene anteposta una barra, verranno cercati soltanto i file nella directory principale del repository.
debug.log debug.log
logs/debug.log
Per impostazione predefinita, gli schemi cercano i file in qualsiasi directory
debug?.log debug0.log
debugg.log
ma non
debug10.log
Un punto interrogativo corrisponde esattamente a un carattere.
debug[0-9].log debug0.log
debug1.log
ma non
debug10.log
Inoltre, possono essere utilizzate le parentesi quadre per cercare un singolo carattere di un intervallo specificato.
debug[01].log debug0.log
debug1.log
ma non
debug2.log
debug01.log
Le parentesi quadre corrispondono a un singolo carattere del set specificato.
debug[!01].log debug2.log
ma non
debug0.log
debug1.log
debug01.log
Un punto esclamativo può essere utilizzato per cercare un qualsiasi carattere ad eccezione di quelli del set specificato.
debug[a-z].log debuga.log
debugb.log
ma non
debug1.log
Gli intervalli possono essere numerici o alfabetici.
Log logs
logs/debug.log
logs/latest/foo.bar
build/logs
build/logs/debug.log
Se non aggiungi una barra, lo schema cercherà sia i file che il contenuto delle directory con il nome specificato. Nelle corrispondenze di esempio a sinistra, sia le directory che i file denominati logs vengono ignorati
logs/ logs/debug.log
logs/latest/foo.bar
build/logs/foo.bar
build/logs/latest/debug.log
L'aggiunta di una barra indica che lo schema è una directory. L'intero contenuto di qualsiasi directory nel repository corrispondente al nome specificato, inclusi tutti i file e le sottodirectory, verrà ignorato
logs/
!logs/important.log
logs/debug.log
logs/important.log
Aspetta un attimo! logs/important.log non dovrebbe essere negato nell'esempio a sinistra?

No! A causa di una peculiarità delle prestazioni di Git, non è possibile negare un file ignorato a causa di uno schema corrispondente a una directory
logs/**/debug.log logs/debug.log
logs/monday/debug.log
logs/monday/pm/debug.log
Un doppio asterisco corrisponde a zero o più directory.
logs/*day/debug.log logs/monday/debug.log
logs/tuesday/debug.log
ma non
logs/latest/debug.log
I caratteri jolly possono essere utilizzati anche nei nomi delle directory.
logs/debug.log logs/debug.log
ma non
debug.log
build/logs/debug.log
Gli schemi che specificano un file in una directory particolare sono relativi alla directory principale del repository (se vuoi, puoi anteporre una barra, ma ciò non fa una grande differenza).

** in queste spiegazioni si presuppone che il file .gitignore si trovi nella directory di primo livello del repository, così come da convenzione. Se il repository contiene più file .gitignore, basta sostituire mentalmente la "directory principale del repository" con la "directory contenente il file .gitignore" (e prendere in considerazione di unirli, per la sanità mentale del team).*

Oltre a questi caratteri, puoi usare # per includere commenti nel file .gitignore:

# ignore all logs
*.log

Puoi usare \ per eseguire l'escape dei caratteri dello schema di .gitignore se sono presenti file o directory che li contengono:

# ignore the file literally named foo[01].txt
foo\[01\].txt

File .gitignore condivisi nel repository

Le regole di git ignore sono generalmente definite in un file .gitignore nella directory principale del repository. Tuttavia, puoi scegliere di definire più file .gitignore in diverse directory del repository. Ogni schema in un determinato file .gitignore viene testato rispetto alla directory che contiene tale file. Tuttavia, per convenzione e come approccio più semplice, è bene definire un singolo file .gitignore nella directory principale. Quando il file .gitignore viene archiviato ne viene creata una versione, così come accade con qualsiasi altro file nel repository, e viene condiviso con gli altri membri del team quando esegui il push. In genere, dovresti includere in .gitignore solo schemi effettivamente utili per gli altri utenti del repository.

Regole di git ignore personali

È inoltre possibile definire schemi di rimozione personali per un determinato repository in un file speciale al percorso .git/info/exclude. Questi schemi non hanno un numero di versione e non sono distribuiti con il repository, quindi è qui che dovresti includere gli schemi che probabilmente saranno utili soltanto a te. Ad esempio, se hai una configurazione di registrazione personalizzata o strumenti di sviluppo speciali che generano file nella directory di lavoro del repository, potresti considerare di aggiungerli a .git/info/exclude per evitare che vengano accidentalmente sottoposti a commit nel repository.

Regole di git ignore globali

Inoltre, puoi definire schemi di git ignore globali per tutti i repository sul sistema locale impostando la proprietà Core.excludesFile di Git. Dovrai creare questo file in autonomia. Se hai dubbi su dove posizionare il file .gitignore globale, la home directory non è una cattiva scelta (e lo rende facile da trovare in seguito). Una volta creato il file, dovrai configurarne la posizione con git config:

$ touch ~/.gitignore
$ git config --global core.excludesFile ~/.gitignore

Presta attenzione a quali schemi scegli di ignorare a livello globale, poiché diversi tipi di file corrispondono a diversi progetti. I file speciali del sistema operativo (ad es. .DS_Store e thumbs.db) o i file temporanei creati da alcuni strumenti di sviluppo sono i candidati ideali per a essere ignorati a livello globale.

Ignorare un file precedentemente sottoposto a commit

Se vuoi ignorare un file di cui hai eseguito il commit in passato, dovrai eliminare tale file dal repository e quindi aggiungere una regola .gitignore per quest'ultimo. Se usi l'opzione --cached con git rm, il file verrà eliminato dal repository, ma rimarrà nella directory di lavoro come file ignorato.

$ echo debug.log >> .gitignore
  
$ git rm --cached debug.log
rm 'debug.log'
  
$ git commit -m "Start ignoring debug.log"

È possibile omettere l'opzione --cached se desideri eliminare il file sia dal repository che dal file system locale.

Esecuzione del commit di un file ignorato

È possibile forzare il commit di un file ignorato nel repository usando l'opzione -f (o --force) con git add:

$ cat .gitignore
*.log
  
$ git add -f debug.log
  
$ git commit -m "Force adding debug.log"

Potresti prendere in considerazione questa procedura se hai definito uno schema generale (come *.log), ma vuoi eseguire il commit di un file specifico. Tuttavia, una soluzione migliore è definire un'eccezione alla regola generale:

$ echo !debug.log >> .gitignore
  
$ cat .gitignore
*.log
!debug.log
  
$ git add debug.log
  
$ git commit -m "Adding debug.log"

Questo approccio è più immediato e meno confusionario per gli altri membri del team.

Accantonamento di un file ignorato

git stash è un'efficace funzione di Git che consente di bloccare temporaneamente e ripristinare le modifiche locali, per permetterti di riapplicarle in seguito. Come ci si aspetterebbe, per impostazione predefinita git stash ignora i file ignorati e accantona solo le modifiche ai file monitorati da Git. Tuttavia, puoi richiamare git stash con l'opzione --all per accantonare anche le modifiche ai file ignorati e non monitorati.

Debug dei file .gitignore

Se gli schemi .gitignore che utilizzi sono complicati, o se ci sono schemi distribuiti su più file .gitignore, può essere difficile individuare il motivo per cui un determinato file viene ignorato. Puoi usare il comando git check-ignore con l'opzione -v (o --verbose) per individuale lo schema che sta causando la rimozione di un determinato file:

$ git check-ignore -v debug.log
.gitignore:3:*.log  debug.log

L'output mostra:

<file containing the pattern> : <line number of the pattern> : <pattern>    <file name>

Puoi inviare più nomi di file a git check-ignore se lo desideri, e i nomi stessi non devono nemmeno corrispondere ai file presenti nel repository.

Pronto per imparare a utilizzare Git?

Prova questo tutorial interattivo.

Inizia ora