Da Anonimo (non verificato) , 29 Aprile 2026

Introduzione

git clone sembra una sola operazione ma in realtà ne compone diverse. Capire i passi aiuta quando si risolvono problemi di clone parziali, clone lenti o default sorprendenti.

La sequenza

  1. Crea la directory di destinazione.
  2. Esegue git init al suo interno.
  3. Aggiunge origin come remote con l'URL di origine.
  4. Configura il refspec predefinito +refs/heads/*:refs/remotes/origin/*.
  5. Esegue git fetch origin per scaricare oggetti e ref.
  6. Determina il branch predefinito (l'HEAD del remote).
  7. Crea un branch locale che lo traccia.
  8. Fa il checkout di quel branch nella working tree.

Vederlo accadere

GIT_TRACE=1 GIT_TRACE_PACKET=1 git clone https://github.com/example/widget.git 2>&1 | head -50

Vedrai negoziazione di capabilities, advertisement dei ref, negoziazione want/have e ricezione del pack.

Wire protocol

Git moderno supporta il protocollo v2 (git config protocol.version 2 o predefinito in 2.26+). Il server pubblicizza solo i ref richiesti invece della lista completa, il che migliora drasticamente i tempi di clone per repo con molti ref.

Varianti

git clone --bare                       # nessuna working tree
git clone --mirror                     # bare + tutti i ref, configurato per mirroring
git clone --depth 1                    # shallow
git clone --filter=blob:none           # partial clone, salta i blob fino al bisogno
git clone --filter=tree:0              # ancora meno dati, tree on-demand
git clone --single-branch              # solo storia di un branch
git clone --branch v1.2.3              # checkout di un branch/tag specifico
git clone --recurse-submodules         # clona anche i submodule
git clone --no-checkout                # salta il popolamento della working tree

Partial clone

I partial clone (--filter) rimandano il download degli oggetti finché non sono necessari. Richiedono supporto del server (la maggior parte degli host moderni ce l'ha):

git clone --filter=blob:none https://github.com/example/big.git
cd big
git log --oneline                  # economico; solo oggetti commit e tree scaricati
git show HEAD:src/main.c           # questo innesca un fetch di blob

Cosa va dove

Dopo un clone riuscito:

  • .git/objects/pack/: il pack file ricevuto dal server.
  • .git/refs/remotes/origin/: ogni branch del server come ref di tracking remoto.
  • .git/HEAD: ref simbolico al nuovo branch locale.
  • .git/config: sezione [remote "origin"] con URL e refspec.

Advertisement lato server

La prima cosa che il server invia in qualsiasi clone è l'advertisement dei ref. Sotto il protocollo v0/v1 questo elenca ogni ref, anche se ne vuoi solo uno; su repo enormi con milioni di ref il solo advertisement potrebbe richiedere secondi. Il protocollo v2 cambia questo: il client invia una richiesta ls-refs specificando pattern, e il server pubblicizza solo i ref corrispondenti:

git -c protocol.version=2 ls-remote origin 'refs/heads/main'
GIT_TRACE_PACKET=1 git -c protocol.version=2 ls-remote origin 2>&1 | head

Per i clone quotidiani lo speedup è invisibile; per i server di hosting è drammatico.

Errori comuni

Clonare un repo enorme su una rete instabile e ricominciare da capo; git clone in 2.30+ supporta il cloning ripristinabile sopra il protocollo HTTP smart, ma solo se il server lo supporta. Altrimenti prima --depth 1, poi git fetch --unshallow dopo. Clonare in ~/Dropbox o un'altra cartella di sync; il client di sync combatterà con Git per il controllo di .git/index. Clonare un repo con submodule e dimenticare --recurse-submodules, finendo con directory submodule vuote. Infine, clonare via HTTPS senza un credential helper ed essere chiesti delle credenziali a ogni fetch; configurane uno una volta.