Introduzione
Un clone shallow scarica solo i più recenti N commit di un branch invece della storia completa. Il risultato è molto più piccolo e veloce da scaricare, al costo di una storia incompleta.
Creare
git clone --depth 1 https://github.com/example/widget.git
git clone --depth 50 https://github.com/example/widget.git
git clone --depth 1 --branch v1.2.3 --single-branch <url>
La directory .git contiene un file shallow che elenca i commit i cui parent sono stati omessi.
Perché shallow
- Build CI: hanno bisogno solo dei sorgenti per HEAD.
- Container e Dockerfile: immagini più piccole.
- Tooling one-shot che non ha bisogno della storia.
Limitazioni
- Non puoi pushare da un clone shallow se il tuo push dipende da commit che il server non ha (raro, ma possibile).
git logsi ferma al confine shallow.- Alcune operazioni (rebase attraverso il confine, blame su righe vecchie) non possono funzionare.
- Fino a Git 2.11 il cloning shallow su HTTP non era supportato; Git moderno lo gestisce.
Approfondire e unshallow
git fetch --depth 100 # estendi la profondità
git fetch --deepen 50 # aggiungi 50 commit in più
git fetch --shallow-since=2024-01-01
git fetch --unshallow # scarica la storia completa
Dopo --unshallow il repo si comporta come un clone normale.
Single-branch e shallow
--single-branch + --depth 1 è il clone più piccolo possibile utile. Per tracciare altri branch dopo:
git remote set-branches --add origin main feature
git fetch origin
Partial clone (un'ottimizzazione diversa)
Se hai bisogno della storia completa ma non di tutti i blob, usa invece un partial clone:
git clone --filter=blob:none <url>
git clone --filter=tree:0 <url>
I partial clone scaricano la storia ma rimandano i blob (o tree) finché non sono necessari. Sono di solito una scelta migliore di shallow quando il server li supporta.
Rilevare lo stato shallow
git rev-parse --is-shallow-repository
cat .git/shallow
Pattern CI
Molti provider CI hanno default shallow clone (depth 1 o 50). Se la tua build esegue git describe o ha bisogno di blame tra versioni, richiedi un clone completo:
# GitHub Actions
- uses: actions/checkout@v4
with:
fetch-depth: 0
File shallow e graft
Il file shallow in .git/ elenca SHA di commit i cui parent sono intenzionalmente mancanti. Git li tratta come root durante la traversata del grafo. Il meccanismo correlato ma deprecato info/grafts ti permetteva di falsificare relazioni parent; usa invece git replace --graft, che è più sicuro e si replica via fetch:
cat .git/shallow
git replace --graft <commit> <new-parent>
git replace -l
git replace -d <commit>
Questo è occasionalmente utile per cucire insieme storie importate senza riscrivere i commit.
Errori comuni
Eseguire git describe in un clone depth-1 e ottenere un errore perché nessun tag annotated è raggiungibile; o scarica i tag (--tags) o usa un clone più profondo. Provare a fare rebase di un feature branch in un clone shallow dove la merge base è oltre il confine shallow; approfondisci prima. Pushare da un clone shallow ed essere sorpresi da "remote rejected"; il server può aver bisogno di oggetti parent mancanti. Infine, trattare i clone shallow come sostituto dei partial clone; risolvono problemi diversi e i partial sono di solito più amichevoli.