Introduction
git clone ressemble à une opération unique mais en compose en réalité plusieurs. Comprendre les étapes aide pour le dépannage des clones partiels, lents ou avec des défauts surprenants.
La séquence
- Crée le répertoire cible.
- Exécute
git inità l'intérieur. - Ajoute
origincomme remote avec l'URL source. - Configure le refspec par défaut
+refs/heads/*:refs/remotes/origin/*. - Exécute
git fetch originpour télécharger objets et refs. - Détermine la branche par défaut (le
HEADdu remote). - Crée une branche locale qui la suit.
- Fait un checkout de cette branche dans l'arborescence de travail.
Le voir se produire
GIT_TRACE=1 GIT_TRACE_PACKET=1 git clone https://github.com/example/widget.git 2>&1 | head -50
Vous verrez la négociation de capacités, l'annonce des refs, la négociation want/have et la réception du pack.
Protocole filaire
Git moderne supporte le protocole v2 (git config protocol.version 2 ou défaut depuis 2.26+). Le serveur n'annonce que les refs demandées plutôt que la liste complète des refs, ce qui améliore considérablement les temps de clone pour les dépôts avec de nombreuses refs.
Variantes
git clone --bare # pas d'arborescence de travail
git clone --mirror # nu + toutes les refs, configuré pour le mirroring
git clone --depth 1 # shallow
git clone --filter=blob:none # clone partiel, saute les blobs jusqu'à besoin
git clone --filter=tree:0 # encore moins de données, trees à la demande
git clone --single-branch # historique d'une seule branche
git clone --branch v1.2.3 # checkout d'une branche/tag spécifique
git clone --recurse-submodules # cloner aussi les sous-modules
git clone --no-checkout # sauter le peuplement de l'arborescence de travail
Clones partiels
Les clones partiels (--filter) reportent le téléchargement d'objets jusqu'à ce qu'ils soient nécessaires. Ils nécessitent le support du serveur (la plupart des hôtes modernes l'ont) :
git clone --filter=blob:none https://github.com/example/big.git
cd big
git log --oneline # bon marché ; seuls les objets commit et tree fetchés
git show HEAD:src/main.c # cela déclenche un fetch de blob
Ce qui va où
Après un clone réussi :
.git/objects/pack/: le pack file reçu du serveur..git/refs/remotes/origin/: chaque branche du serveur comme ref de tracking distant..git/HEAD: ref symbolique vers la nouvelle branche locale..git/config: section[remote "origin"]avec URL et refspec.
Annonce côté serveur
La première chose que le serveur envoie dans tout clone est l'annonce des refs. Sous le protocole v0/v1, cela liste chaque ref, même si vous n'en voulez qu'une ; sur d'énormes dépôts avec des millions de refs, l'annonce seule peut prendre des secondes. Le protocole v2 change cela : le client envoie une requête ls-refs spécifiant des motifs, et le serveur n'annonce que les refs correspondantes :
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
Pour les clones quotidiens, l'accélération est invisible ; pour les serveurs d'hébergement, elle est dramatique.
Erreurs fréquentes
Cloner un énorme dépôt sur un réseau instable et recommencer depuis zéro ; git clone en 2.30+ supporte le clone reprenable sur le smart HTTP, mais seulement si le serveur le supporte. Sinon, --depth 1 d'abord, puis git fetch --unshallow plus tard. Cloner dans ~/Dropbox ou un autre dossier de synchronisation ; le client de synchronisation luttera avec Git pour le contrôle de .git/index. Cloner un dépôt avec sous-modules et oublier --recurse-submodules, finissant avec des répertoires de sous-modules vides. Enfin, cloner via HTTPS sans assistant d'identifiants et être interrogé pour les identifiants à chaque fetch ; configurez-en un une fois.