- #golang
- #cli
- #git
- #tooling
- #design
Gestire file locali fuori da Git: un problema piccolo ma reale
Alcuni file servono solo localmente e non dovrebbero finire nel repository. In questo post parto da un problema reale e spiego le scelte di design dietro una piccola CLI per gestirli senza usare .gitignore.
-2 min read
Il problema (reale)
Nel mio lavoro utilizzo in modo abbastanza intensivo agenti IA per lo sviluppo. Questo comporta una serie di file e directory locali che:
- servono solo a me
- contengono configurazioni personali o sperimentali
- non devono finire nel repository
Il problema è che questi file non sono sempre adatti a finire in .gitignore:
.gitignoreè versionato- le regole diventano rapidamente rumorose
- spesso valgono solo per una persona o un setup specifico
Git offre già una soluzione: .git/info/exclude.
Il punto è che:
- è poco usato
- è scomodo da gestire a mano
- non scala quando i file iniziano ad essere tanti
Da qui nasce il problema che voglio risolvere.
Cosa NON volevo fare
Prima di spiegare cosa ho costruito, vale la pena chiarire cosa non volevo:
- ❌ un nuovo formato tipo
.gitignore - ❌ un tool che modifica il repository
- ❌ un sistema di regole magiche o implicite
- ❌ qualcosa di iper-configurabile
L’obiettivo non era “gestire Git meglio”. Era gestire file locali in modo esplicito e riproducibile.
L’idea di base
L’idea è molto semplice:
- definisco quali file o directory sono locali
- li individuo usando glob pattern
- li copio in una directory separata
- se il progetto è un repository Git, li escludo usando
.git/info/exclude
Git è un effetto collaterale utile, non il cuore del tool.
Una decisione importante: cos’è la “root” del progetto
Una delle prime scelte di design è stata questa:
La root del progetto è sempre esplicita.
Regola finale:
- se passo
--root, quella è la root - altrimenti la root è la directory corrente
- Git non influisce mai su questa scelta
Questo evita:
- comportamenti impliciti
- scan verso l’alto
- ambiguità tra progetto e repository
Progetto e repository non sono la stessa cosa, anche se spesso coincidono.
Perché usare i glob
Ho scelto di usare i glob pattern (con supporto a **) perché:
- sono semplici da leggere
- sono espressivi quanto basta
- non richiedono regex
- funzionano bene su path relativi
Esempio:
exclude:
- "**/.env.local"
- "tools/agent/**"
L’idea è che il tool seleziona file, non directory logiche. Le directory vengono espanse solo come conseguenza.
Cosa fa (e cosa no) la prima versione
La v1 del tool fa solo questo:
- scansiona una root usando glob
- raccoglie i file matchati
- li copia preservando i path relativi
- opzionalmente aggiorna
.git/info/exclude
E soprattutto non fa:
- restore
- sync bidirezionale
- diff
- include / exclude avanzati
Tutto questo potrà venire dopo, se servirà davvero.
Perché questo progetto ha senso per CeccheLab
Questo progetto rispetta alcune regole che per me sono importanti:
- nasce da un problema reale
- ha un perimetro chiaro
- evita feature premature
- separa bene concetti diversi
Ed è abbastanza piccolo da:
- essere mantenibile
- generare più di un articolo
- restare onesto
Prossimi passi
Nei prossimi post entrerò più nel dettaglio:
- il design dell’algoritmo di scan
- la struttura della CLI
- l’implementazione in Go
Senza promettere troppo. Solo codice che serve davvero.