modulo 07 / lezione 34
Casi reali, debugging della storia, recupero
Submodule e alternative (subtree, monorepo)
Conoscere submodule e capire perché spesso una soluzione diversa è migliore.
Submodule e alternative (subtree, monorepo)
Un submodule è un repository Git dentro un altro repository Git. Il repo principale non salva i file del submodule come normali file: salva un riferimento a uno specifico commit del repository esterno, più la configurazione in .gitmodules.
È potente, ma richiede disciplina. Molti problemi con i submodule nascono dal trattarli come semplici cartelle.
Perché questa lezione conta
Prima o poi un team deve condividere codice tra progetti: librerie interne, temi, SDK, componenti, documentazione, strumenti di build. Git offre submodule e subtree, ma spesso la scelta migliore è un package versionato o un monorepo.
La competenza non è “sapere il comando submodule”. È scegliere il modello giusto per il ciclo di lavoro del team.
Obiettivo operativo
Alla fine della lezione devi saper aggiungere, clonare e aggiornare un submodule, riconoscere i suoi rischi operativi e confrontarlo con subtree, package manager e monorepo.
Come funziona un submodule
Aggiunta:
git submodule add git@github.com:org/lib.git vendor/lib
git commit -m "build: aggiungi submodule lib"
Git crea o aggiorna:
.gitmodules
vendor/lib -> gitlink verso uno SHA specifico
Nel repo principale il submodule è registrato come commit preciso, non come “ultimo main”. Questo è utile per riproducibilità, ma significa che aggiornare la libreria richiede un commit anche nel repo principale.
Clonare correttamente
Clonazione diretta:
git clone --recurse-submodules <repo>
Se hai già clonato:
git submodule update --init --recursive
Dopo un pull che cambia SHA del submodule:
git submodule update --recursive
Senza questi comandi, la cartella può restare vuota o puntare a un commit diverso da quello atteso.
Aggiornare un submodule
Per spostare il submodule a una versione nuova:
cd vendor/lib
git fetch origin
git switch main
git pull --ff-only
cd ../..
git status
git add vendor/lib
git commit -m "build: aggiorna lib submodule"
Il commit finale nel repo principale registra il nuovo SHA del submodule.
git submodule update --remote può automatizzare parte del processo, ma va usato con attenzione: devi comunque controllare cosa stai portando dentro.
Rischi frequenti
Detached HEAD nel submodule. Dopo submodule update, spesso sei su uno SHA, non su un branch. Se fai commit lì senza creare branch, puoi perderne traccia.
CI non configurata. La pipeline deve clonare con submodule o inizializzarli.
Permessi separati. Chi clona il repo principale deve avere accesso anche al repo del submodule.
Review spezzata. La PR del repo principale mostra solo cambio SHA; il diff vero è nel repo del submodule.
Alternative
| Soluzione | Quando ha senso | Costo |
|---|---|---|
| Submodule | dipendenza Git precisa, repo separati, release indipendenti | onboarding e CI più complessi |
| Subtree | vuoi copiare una dipendenza dentro una cartella mantenendo traccia dell’origine | sincronizzazione manuale |
| Package versionato | libreria usata da più progetti con versioni chiare | serve pubblicazione pacchetto |
| Monorepo | codice accoppiato, release coordinate, tooling condiviso | governance e build più sofisticate |
| Copia manuale | prototipo o codice statico raramente aggiornato | rischio divergenza |
Subtree in breve
Esempio:
git subtree add --prefix=vendor/lib git@github.com:org/lib.git main --squash
git subtree pull --prefix=vendor/lib git@github.com:org/lib.git main --squash
Con subtree i file entrano nel repo principale. Chi clona non deve inizializzare nulla. In cambio, aggiornare e contribuire indietro richiede procedure più esplicite.
Criterio decisionale
Scegli submodule solo se:
- il repo esterno deve restare davvero indipendente;
- vuoi pin esatto a commit specifici;
- il team accetta comandi extra in clone, CI e onboarding;
- le review cross-repo sono gestite.
Se il codice evolve insieme al progetto, valuta monorepo o workspace. Se è una libreria consumata da molti, valuta package manager e SemVer.
Laboratorio guidato
In un ambiente sandbox:
- crea repo
appe repolib; - aggiungi
libcome submodule inapp; - clona
appsenza--recurse-submodulese osserva il problema; - inizializza con
git submodule update --init --recursive; - fai un commit in
lib; - aggiorna il riferimento in
app; - ripeti lo scenario con
git subtree add.
Output atteso
Una decisione documentata:
Codice condiviso:
Frequenza aggiornamento:
Chi lo modifica:
Serve pin a commit:
Serve release package:
Scelta: submodule / subtree / package / monorepo
Motivo:
Procedura onboarding:
Procedura CI:
Errori comuni
Pensare che submodule sia una cartella normale. È un altro repo.
Dimenticare --recurse-submodules. Il clone non è completo.
Fare commit nel submodule in detached HEAD. Crea lavoro difficile da ritrovare.
Usare submodule per codice che evolve insieme all’app. Spesso un monorepo è più semplice.
Checklist di verifica
- so aggiungere un submodule;
- so clonare e inizializzare submodule;
- so aggiornare lo SHA registrato nel repo principale;
- so spiegare i rischi in CI e review;
- so scegliere tra submodule, subtree, package e monorepo.
Collegamenti
- Modulo: Casi reali, debugging della storia, recupero - lezione 34 del corso.
- Si collega a tag, SemVer, monorepo e workflow di team.