Architecture Decision Records - ADR260201e
2026/02/01Self-versioning di .side-tracked via git plumbing
Autore: Marco Orlandin, Architect
Data: 01 Febbraio 2026
Status: Implementato
Progetto: git-side (open-source, sviluppato per Solexma LLC)
Constraint principali: La lista dei file tracciati deve viaggiare con push/pull, non deve vivere nel repo principale, deve essere versionata insieme ai file che descrive
Contesto e problema
git-side tiene traccia di quali file e directory sono "side-tracked", cioè versionati nel side repo. Questa lista deve essere persistente e, soprattutto, deve viaggiare con i dati quando si fa push/pull verso un remote.
Se faccio push dei miei file "a lato" e un collega fa pull, il collega deve sapere quali path sono tracciati. Senza questa informazione, git side auto non saprebbe cosa sincronizzare.
Il problema è dove e come memorizzare questa lista:
- Non può stare nel repo principale (zero inquinamento).
- Non può stare solo in un file di configurazione locale (non viaggia con push/pull).
- Deve vivere dentro il side repo stesso, versionata come qualsiasi altro file.
Ma il side repo è un bare repository e non ha una working directory propria. Il file .side-tracked non esiste su disco nella directory del progetto. Come si aggiunge un file "virtuale" a un bare repo?
Requisiti non funzionali
- La lista tracciati deve essere versionata nel side repo
- Deve viaggiare automaticamente con push e pull
- Non deve creare file nella directory del progetto
- Deve essere aggiornabile atomicamente ad ogni add/rm
Opzioni valutate
Opzione 1: File di configurazione nella config directory di sistema
- Pro: Semplice da implementare. Lettura/scrittura immediata.
- Contro: Non viaggia con push/pull. Ogni macchina avrebbe una lista diversa. Il collega che fa pull non sa cosa tracciare.
Opzione 2: File .side-tracked nella directory del progetto
- Pro: Visibile, facile da editare, git lo traccia normalmente.
- Contro: Viola il principio di zero inquinamento. Apparirebbe in
git statusdel repo principale.
Opzione 3: Git notes sul side repo
- Pro: Meccanismo Git-native per metadati.
- Contro: Non pensato per questo uso. API scomoda. Non si sincronizza automaticamente con push/pull standard.
Opzione 4: Git plumbing (hash-object + update-index)
- Pro: Il file vive nell'indice del bare repo senza esistere su disco. Viene committato normalmente. Viaggia con push/pull. Completamente Git-native.
- Contro: Richiede conoscenza dei comandi plumbing. Implementazione meno intuitiva.
Decisione
Scelto il git plumbing: il file .side-tracked viene scritto nell'indice del bare repo tramite hash-object e update-index, senza mai toccare il filesystem della directory del progetto.
Motivazioni principali:
- Self-contained: la lista vive dove vivono i dati che descrive.
- Sincronizzazione automatica: push/pull portano la lista insieme ai file.
- Versionata: ogni modifica alla lista è un commit, con storia e diff.
- Invisibile: nessun file aggiuntivo nella directory del progetto.
Implementazione passo-passo
- Scrittura: La lista dei path tracciati (uno per riga, ordinamento deterministico via
BTreeSet) viene serializzata in una stringa. - hash-object:
git hash-object -w --stdinscrive il contenuto nel database oggetti del bare repo e restituisce lo SHA. - update-index:
git update-index --add --cacheinfo 100644,<sha>,.side-trackedaggiunge il file all'indice con il nome.side-tracked. - Commit: Il file viene incluso nel prossimo commit del side repo insieme ai file tracciati.
- Lettura: Al pull,
.side-trackedviene estratto dall'albero del commit e usato per ricostruire la lista dei path.
Conseguenze osservate
- La lista viaggia correttamente con push/pull: chi clona il side repo sa esattamente cosa tracciare.
- L'ordinamento deterministico (
BTreeSet) garantisce che la lista sia identica indipendentemente dall'ordine di aggiunta. - Nessun file
.side-trackedappare mai nella directory del progetto. - Lezioni apprese:
- I comandi plumbing di Git sono potenti e sottovalutati.
hash-object+update-indexrisolvono elegantemente il problema dei "file virtuali" nei bare repo. - Il self-versioning elimina un'intera classe di problemi di sincronizzazione.
- Documentare il meccanismo è importante: il plumbing non è ovvio per chi legge il codice per la prima volta.
- I comandi plumbing di Git sono potenti e sottovalutati.
Stack utilizzato
- Linguaggio: Rust (Edition 2024, MSRV 1.85)
- Git plumbing:
git hash-object,git update-index - Struttura dati:
BTreeSetper ordinamento deterministico e deduplicazione
Quando considerare questo approccio
Se devi versionare metadati o file di configurazione dentro un bare repository senza toccare la working directory:
- Tool che gestiscono repository Git dall'esterno
- Sistemi che devono sincronizzare metadata insieme ai dati
- Qualsiasi contesto in cui un file deve "vivere" nel repo senza esistere su disco
Il plumbing Git è la risposta. È meno accessibile del porcelain, ma risolve problemi che il porcelain non può affrontare.
Hai un caso simile? Contattami. Valutiamo insieme se il plumbing è la strada giusta.