git bundle crée un fichier autonome contenant tout ou partie d'un
dépôt Git, transférable par clé USB, email ou tout autre moyen
hors-ligne. C'est la solution pour les environnements air-gapped,
les transferts entre réseaux isolés et les sauvegardes portables. Ce
guide vous apprend à créer un bundle, vérifier son contenu et cloner
ou puller depuis un bundle, avec un exemple complet de workflow
hors-ligne.
Prérequis : Remotes fondamentaux et Sélection de révisions.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Créer un bundle complet d'un dépôt pour transfert hors-ligne
- Créer des bundles incrémentaux pour des mises à jour légères
- Vérifier l'intégrité d'un bundle avant de l'utiliser
- Cloner ou puller depuis un fichier bundle
Quand utiliser git bundle ?
Section intitulée « Quand utiliser git bundle ? »Le point commun de ces situations est l'absence de canal réseau direct entre
les deux dépôts. Tant qu'un git push ou un git fetch peut aboutir, un remote
classique reste plus simple. Le bundle prend le relais dès que le transport
devient un fichier à déplacer à la main, avec l'avantage décisif de conserver
l'historique complet et les empreintes des commits : le dépôt reconstitué à
l'arrivée est identique, pas une copie approximative.
- Environnement air-gapped : serveurs sans accès internet
- Transfert entre réseaux : les deux machines ne se voient pas
- Sauvegarde portable : un fichier unique contenant tout l'historique
- Bande passante limitée : envoyer un fichier compressé par email
- Onboarding : donner le repo complet à un nouveau développeur sur clé USB
Créer un bundle complet
Section intitulée « Créer un bundle complet »git bundle create prend un nom de fichier suivi des mêmes arguments que
git rev-list : c'est ce qui permet de choisir précisément ce qu'on emporte.
L'option --all désigne toutes les références du dépôt, branches et tags
compris. Le fichier produit est un objet Git valide que la machine de
destination traitera exactement comme un dépôt distant.
# Bundle contenant TOUT le dépôt (toutes les branches, tous les tags)git bundle create mon-projet.bundle --allLe fichier mon-projet.bundle contient l'intégralité du dépôt : tous
les commits, branches, tags et objets Git. C'est l'équivalent d'un
clone complet dans un fichier unique.
Pour bundler uniquement une branche :
git bundle create main-only.bundle mainImporter un bundle
Section intitulée « Importer un bundle »Cloner depuis un bundle
Section intitulée « Cloner depuis un bundle »Un bundle contenant un historique complet se clone comme n'importe quelle URL.
Git enregistre alors le chemin du fichier comme remote origin, ce qui
pose problème dès que la clé USB est retirée : toute commande réseau échouera.
Repointer origin juste après le clone évite d'y revenir plus tard dans
l'urgence.
git clone mon-projet.bundle mon-projetcd mon-projetLe bundle est traité comme un remote. Après le clone, configurez le vrai remote :
git remote set-url origin https://github.com/org/mon-projet.gitAjouter un bundle comme remote
Section intitulée « Ajouter un bundle comme remote »Quand le dépôt existe déjà côté destination, il n'y a rien à cloner : on ajoute
le bundle comme remote supplémentaire et on récupère ses références.
L'intérêt est de garder l'origin existant intact et de pouvoir comparer les
deux sources avant de fusionner quoi que ce soit.
git remote add usb /media/usb/mon-projet.bundlegit fetch usbgit merge usb/mainLe fetch affiche une ligne par référence importée, préfixée de
* [new branch]. Tant que vous n'avez pas lancé le merge, votre branche
locale n'a pas bougé : git log --oneline usb/main permet donc d'inspecter ce
qui arrive avant de l'intégrer.
Vérifier un bundle
Section intitulée « Vérifier un bundle »Avant d'importer, validez l'intégrité :
git bundle verify mon-projet.bundlemon-projet.bundle is okayThe bundle contains these 4 refs:1fefc49f24e0414d7ff326e6c41cd9cff17220c0 refs/heads/mainfb239952b2534d694c54abd6c55ab26a78801656 refs/heads/develop1fefc49f24e0414d7ff326e6c41cd9cff17220c0 refs/tags/v1.0.01fefc49f24e0414d7ff326e6c41cd9cff17220c0 HEADThe bundle records a complete history.The bundle uses this hash algorithm: sha1Trois lignes méritent votre attention. HEAD apparaît dans la liste parce que
--all l'inclut : c'est normal, ce n'est pas une branche en double. The
bundle records a complete history confirme qu'aucun commit préalable n'est
requis, donc que ce fichier suffit à reconstruire le dépôt. Enfin, l'algorithme
d'empreinte doit correspondre à celui du dépôt de destination : un bundle
sha256 est illisible par un dépôt sha1.
Si le bundle est incomplet (incrémental), verify remplace cette ligne par
The bundle requires this ref: suivie des commits absents. Aucun import n'est
possible tant que ces commits ne sont pas déjà présents en local.
Bundles incrémentaux
Section intitulée « Bundles incrémentaux »Pour les mises à jour régulières, inutile de re-bundler tout le dépôt. Créez des bundles contenant uniquement les nouveaux commits :
-
Premier transfert, bundle complet :
Fenêtre de terminal git bundle create initial.bundle --all# Notez le dernier commit inclusgit rev-parse HEAD# a1b2c3d4... -
Transferts suivants, uniquement les nouveautés :
Fenêtre de terminal # Depuis le dernier commit transférégit bundle create update-1.bundle a1b2c3d4..HEAD --all -
Sur la machine de destination, appliquer l'incrément :
Fenêtre de terminal git bundle verify update-1.bundle # Vérifier les pré-requisgit fetch /chemin/update-1.bundle main:remotes/usb/maingit merge usb/mainLe
fetchcrée la référence localerefs/remotes/usb/main, ce qui rend l'incrément consultable avecgit log usb/mainavant de fusionner.
Dans la commande de l'étape 2, la plage et --all se combinent sans se
contredire : l'exclusion a1b2c3d4.. s'applique à toutes les références
sélectionnées par --all. Vous obtenez donc un fichier qui contient toutes les
branches, mais amputées de l'historique déjà transféré. Le verify sur la
machine de destination affichera The bundle requires this ref: avec
l'empreinte a1b2c3d4 : c'est la preuve que l'incrément a bien fonctionné, pas
une erreur.
Utiliser des tags comme repères
Section intitulée « Utiliser des tags comme repères »Retenir un identifiant de commit à la main ne tient pas dans la durée. Un tag posé après chaque transfert matérialise le point de reprise directement dans le dépôt : au transfert suivant, la plage à empaqueter se lit sans consulter de notes extérieures. Le tag reste local tant que vous ne le poussez pas, il ne pollue donc pas le dépôt partagé.
# Après chaque transfert, tagger le dernier commit envoyégit tag last-bundle-v1
# Au prochain transfertgit bundle create update.bundle last-bundle-v1..HEAD --allgit tag last-bundle-v2Workflow air-gapped complet
Section intitulée « Workflow air-gapped complet »Le schéma ci-dessous résume l'enchaînement sur deux tours : un transfert initial complet, puis un incrément. Lisez-le colonne par colonne, la colonne du milieu représentant le seul élément physique qui traverse la frontière entre les deux réseaux. Le point à ne pas rater est le tag posé après chaque envoi sur la machine connectée : c'est lui qui garantit qu'aucun commit ne sera oublié entre deux transferts.
Machine A (connectée) Clé USB Machine B (isolée)───────────────────── ──────────── ─────────────────────git bundle create copier git clone bundle projet.bundle --all projet.bundle projet git remote set-url origin ...
[... plus tard ...]
git bundle create copier git bundle verify update.bundle update.bundle git fetch update tag-v1..HEAD --all git mergegit tag tag-v2Lister le contenu d'un bundle
Section intitulée « Lister le contenu d'un bundle »list-heads répond à une question précise : quelles branches et quels tags ce
fichier contient-il. Contrairement à verify, il ne contrôle rien et ne dit
pas si l'historique est complet. Utilisez-le pour vérifier qu'une branche
attendue est bien du voyage avant de transporter le fichier.
git bundle list-heads mon-projet.bundle1fefc49f24e0414d7ff326e6c41cd9cff17220c0 refs/heads/mainfb239952b2534d694c54abd6c55ab26a78801656 refs/heads/develop1fefc49f24e0414d7ff326e6c41cd9cff17220c0 refs/tags/v1.0.01fefc49f24e0414d7ff326e6c41cd9cff17220c0 HEADDépannage
Section intitulée « Dépannage »Ces quatre cas représentent la quasi-totalité des blocages rencontrés avec les
bundles. Le dernier est le plus déroutant parce qu'il ne produit aucune
erreur : unbundle importe bien les objets dans le dépôt, mais ne crée
aucune référence, si bien que git log et git branch ne montrent rien de
nouveau. C'est le comportement attendu de la commande, pas un dysfonctionnement.
| Symptôme | Cause probable | Solution |
|---|---|---|
verify dit « prerequisite commit missing » | Bundle incrémental, historique manquant | Importez d'abord le bundle complet |
| Bundle très volumineux | Contient tout l'historique + gros fichiers | Utilisez --since ou des plages de commits |
clone depuis bundle : remote invalide | URL du bundle comme remote | git remote set-url origin <vraie-url> |
unbundle ne fait rien de visible | Les objets sont importés mais pas les branches | Utilisez fetch au lieu de unbundle |
À retenir
Section intitulée « À retenir »git bundle createempaquète tout ou partie d'un dépôt dans un fichier uniquegit bundle verifyvalide l'intégrité avant import- Clone ou fetch depuis un bundle comme depuis un remote
- Les bundles incrémentaux (plage de commits) réduisent la taille des transferts
- Solution idéale pour les environnements air-gapped et les transferts hors-ligne