Architecture Decision Records - ADR260201a

2026/02/01

Identità progetto tramite initial commit SHA

Autore: Marco Orlandin, Architect
Data: 01 Febbraio 2026
Status: Implementato
Progetto: git-side (open-source, sviluppato per Solexma LLC)
Constraint principali: Stabilità tra clone, indipendenza dal path del filesystem e dal remote URL, determinismo, zero inquinamento del repo principale

Contesto e problema

git-side è un subcommand Git che versiona file "a lato" del repository principale, in un bare repo separato. Per funzionare, ha bisogno di associare ogni progetto Git al proprio side repository in modo stabile e univoco.

L'identificatore deve sopravvivere a situazioni reali: clone su macchine diverse, cambio di directory, rename del remote, fork. Se clono lo stesso progetto su un altro computer, git-side deve ritrovare (o ricreare) il side repo corretto.

Il problema è che nessun identificatore "ovvio" di un repo Git è abbastanza stabile:

  • Il path del filesystem cambia tra macchine, utenti, mount point.
  • Il remote URL non esiste nei repo senza remote, e può cambiare (fork, migrazioni, rename dell'organizzazione).
  • Un UUID generato richiederebbe un file di configurazione dentro il repo principale, violando il principio fondante di zero inquinamento.

Requisiti non funzionali

  • Univocità: due progetti diversi non devono mai condividere lo stesso identificatore
  • Immutabilità: l'identificatore non deve cambiare nel tempo
  • Disponibilità universale: deve esistere in ogni repo Git, anche senza remote
  • Zero inquinamento: non deve richiedere file aggiuntivi nel repo principale
  • Performance: il recupero dell'identificatore deve essere rapido

Opzioni valutate

Opzione 1: Path assoluto del filesystem

  • Pro: Immediato, sempre disponibile, zero computazione.
  • Contro: Cambia tra macchine, utenti, mount point. Un clone dello stesso progetto avrebbe un side repo diverso. Non portabile.

Opzione 2: Remote URL (origin)

  • Pro: Identifica univocamente il progetto se esiste un remote.
  • Contro: Non tutti i repo hanno un remote. L'URL può cambiare (rename, fork, migrazione provider). Repo locali senza remote sarebbero esclusi.

Opzione 3: UUID generato salvato in un file nel repo

  • Pro: Univoco e stabile per definizione.
  • Contro: Richiede un file nel repo principale (es. .git-side-id). Viola il principio fondamentale di zero inquinamento. Ogni collaboratore vedrebbe il file, anche chi non usa git-side.

Opzione 4: SHA del primo commit (initial commit)

  • Pro: Immutabile (il primo commit non cambia mai), univoco per progetto, disponibile in ogni repo con almeno un commit, stabile tra clone.
  • Contro: Non esiste prima del primo commit (edge case gestibile). Collisione teoricamente possibile ma praticamente irrilevante.

Decisione

Scelto lo SHA del primo commit (git rev-list --max-parents=0 HEAD) come identificatore univoco del progetto.

Motivazioni principali:

  1. Immutabile: il primo commit è un fatto storico, non cambia mai.
  2. Universale: ogni repo Git con almeno un commit ce l'ha.
  3. Zero inquinamento: non serve nessun file aggiuntivo nel repo principale.
  4. Stabile tra clone: stesso progetto, stesso SHA, su qualsiasi macchina.

La location del side repo diventa: <base_path>/git-side/<initial-commit-sha>/.

Implementazione passo-passo

  1. Recupero SHA: git rev-list --max-parents=0 HEAD restituisce lo SHA del primo commit.
  2. Cache path→SHA: Un file cache mappa i path dei repo già visitati al loro initial commit SHA, evitando di ricalcolarlo ad ogni invocazione.
  3. Path personalizzabile: git side init --path <dir> permette di sovrascrivere il base path per un progetto specifico, memorizzato in un file paths separato.
  4. Lazy init: Il side repo viene creato solo al primo git side add, non prima.
  5. Location di sistema: Il base path segue le convenzioni della piattaforma: ~/Library/Application Support/git-side/ su macOS, ~/.local/share/git-side/ su Linux.

Conseguenze osservate

  • Stabilità verificata su oltre 150 repository in 48 ore di testing.
  • Nessuna collisione di identità riscontrata.
  • Clone dello stesso progetto su macchine diverse ritrovano correttamente il proprio side repo quando si usa push/pull via remote.
  • Lezioni apprese:
    • L'identità di un repo Git è già nel suo DNA: il primo commit è l'impronta digitale più affidabile.
    • La cache path→SHA è essenziale per la performance: senza, ogni comando richiederebbe un git rev-list.
    • L'edge case "repo senza commit" si gestisce con un messaggio chiaro, non con workaround.

Stack utilizzato

  • Linguaggio: Rust (Edition 2024, MSRV 1.85)
  • Path resolution: crate dirs (XDG-compliant, cross-platform)
  • Git: Shell-out a git rev-list

Quando considerare questo approccio

Se hai bisogno di identificare univocamente un repository Git senza modificarlo:

  • Tool esterni che lavorano "a fianco" di un repo
  • Sistemi di caching o metadata per-progetto
  • Qualsiasi contesto in cui il path del filesystem non è stabile

Lo SHA del primo commit è l'identificatore più robusto disponibile senza aggiungere nulla al repo.

Hai un caso simile? Contattami. Valutiamo insieme l'approccio migliore per il tuo contesto.