Git 🌙
Chapters â–Ÿ 2nd Edition

7.12 Utilitaires Git - Empaquetage (bundling)

Empaquetage (bundling)

Bien que nous ayons dĂ©jĂ  abordĂ© les mĂ©thodes les plus communes de transfert de donnĂ©es Git par rĂ©seau (HTTP, SSH, etc.), il existe en fait une mĂ©thode supplĂ©mentaire qui n’est pas beaucoup utilisĂ©e mais qui peut s’avĂ©rer utile.

Git est capable d’empaqueter ses donnĂ©es dans un fichier unique. Ceci peut servir dans de nombreux scĂ©narios. Le rĂ©seau peut ĂȘtre en panne et vous souhaitez envoyer des modifications Ă  vos collĂšgues. Peut-ĂȘtre ĂȘtes-vous en train de travailler Ă  distance et vous ne pouvez pas vous connecter au rĂ©seau local pour des raisons de sĂ©curitĂ©. Peut-ĂȘtre que votre carte rĂ©seau ou votre carte wifi vient de tomber en panne. Peut-ĂȘtre encore n’avez-vous pas accĂšs Ă  un serveur partagĂ©, et vous souhaitez envoyer Ă  quelqu’un des mises Ă  jour sans devoir transfĂ©rer 40 commits via format-patch.

Ce sont des situations oĂč la commande git bundle est utile. La commande bundle va empaqueter tout ce qui serait normalement poussĂ© sur le rĂ©seau avec une commande git push dans un fichier binaire qui peut ĂȘtre envoyĂ© Ă  quelqu’un par courriel ou copiĂ© sur une clĂ© USB, puis de le dĂ©paqueter dans un autre dĂ©pĂŽt.

Voyons un exemple simple. Supposons que vous avez un dépÎt avec deux commits :

$ git log
commit 9a466c572fe88b195efd356c3f2bbeccdb504102
Author: Scott Chacon <schacon@gmail.com>
Date:   Wed Mar 10 07:34:10 2010 -0800

    second commit

commit b1ec3248f39900d2a406049d762aa68e9641be25
Author: Scott Chacon <schacon@gmail.com>
Date:   Wed Mar 10 07:34:01 2010 -0800

    first commit

Si vous souhaitez envoyer ce dĂ©pĂŽt Ă  quelqu’un et que vous n’avez pas accĂšs en poussĂ©e Ă  un dĂ©pĂŽt, ou que simplement vous ne voulez pas en crĂ©er un, vous pouvez l’empaqueter avec git bundle create.

$ git bundle create repo.bundle HEAD master
DĂ©compte des objets: 6, fait.
Delta compression using up to 2 threads.
Compression des objets: 100% (2/2), fait.
Écriture des objets : 100% (6/6), 441 bytes, fait.
Total 6 (delta 0), reused 0 (delta 0)

À prĂ©sent, vous avez un fichier repo.bundle qui contient toutes les donnĂ©es nĂ©cessaires pour recrĂ©er la branche master du dĂ©pĂŽt. Avec la commande bundle, vous devez lister toutes les rĂ©fĂ©rences ou les intervalles spĂ©cifiques de commits que vous voulez inclure. Si vous le destinez Ă  ĂȘtre clonĂ© ailleurs, vous devriez aussi ajouter HEAD comme rĂ©fĂ©rence, comme nous l’avons fait.

Vous pouvez envoyer ce fichier repo.bundle par courriel, ou le copier sur une clé USB et la tendre à un collÚgue.

De l’autre cĂŽtĂ©, supposons qu’on vous a envoyĂ© ce fichier repo.bundle et que vous voulez travailler sur le projet. Vous pouvez cloner le fichier binaire dans un rĂ©pertoire, de la mĂȘme maniĂšre que vous le feriez pour une URL.

$ git clone repo.bundle repo
Initialized empty Git repository in /private/tmp/bundle/repo/.git/
$ cd repo
$ git log --oneline
9a466c5 second commit
b1ec324 first commit

Si vous n’incluez pas HEAD dans les rĂ©fĂ©rences, vous devez aussi spĂ©cifier -b master ou n’importe quelle branche incluse dans le paquet car sinon, il ne saura pas quelle branche extraire.

Maintenant, supposons que vous faites 3 commits et que vous voulez renvoyer ces nouveaux commits via courriel ou clé USB.

$ git log --oneline
71b84da last commit - second repo
c99cf5b fourth commit - second repo
7011d3d third commit - second repo
9a466c5 second commit
b1ec324 first commit

Nous devons dĂ©jĂ  dĂ©terminer l’intervalle de commits que nous voulons inclure dans le colis. À la diffĂ©rence des protocoles rĂ©seau qui calculent automatiquement l’ensemble minimum des donnĂ©es Ă  transfĂ©rer, nous allons devoir les dĂ©finir manuellement. Ici, vous pourriez tout Ă  fait lancer la mĂȘme commande et empaqueter le dĂ©pĂŽt complet, ce qui marcherait mais c’est mieux de n’empaqueter que la diffĂ©rence ‑ seulement les 3 commits que nous avons localement crĂ©Ă©s.

Pour le faire, vous allez devoir calculer la diffĂ©rence. Comme dĂ©crit dans Plages de commits, vous pouvez faire rĂ©fĂ©rence Ă  un intervalle de commits de diffĂ©rentes maniĂšres. Pour dĂ©signer les trois commits que nous avons dans notre branche master et qui n’était pas dans la branche que nous avons initialement clonĂ©e, nous pouvons utiliser quelque chose comme origin/master..master ou master ^origin/master. Vous pouvez tester cela avec la sortie de la commande log.

$ git log --oneline master ^origin/master
71b84da last commit - second repo
c99cf5b fourth commit - second repo
7011d3d third commit - second repo

Comme nous avons maintenant la liste des commits que nous voulons inclure dans le colis, empaquetons-les. Cela est rĂ©alisĂ© avec la commande git bundle create, suivie d’un nom de fichier et des intervalles des commits que nous souhaitons inclure.

$ git bundle create commits.bundle master ^9a466c5
Comptage des objets : 11, fait.
Delta compression using up to 2 threads.
Compression des objets : 100% (3/3), fait.
Écriture de objets : 100% (9/9), 775 bytes, fait.
Total 9 (delta 0), reused 0 (delta 0)

Nous avons Ă  prĂ©sent un fichier commits.bundle dans notre rĂ©pertoire. Si nous le prenons et l’envoyons Ă  un partenaire, il pourra l’importer dans le dĂ©pĂŽt d’origine, mĂȘme si du travail a Ă©tĂ© ajoutĂ© entre temps.

Quand il rĂ©cupĂšre le colis, il peut l’inspecter pour voir ce qu’il contient avant de l’importer dans son dĂ©pĂŽt. La premiĂšre commande est bundle verify qui va s’assurer que le fichier est une fichier bundle Git valide et que le dĂ©pĂŽt contient tous les ancĂȘtres nĂ©cessaires pour appliquer correctement le colis.

$ git bundle verify ../commits.bundle
Le colis contient 1 référence :
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
Le colis exige cette référence
9a466c572fe88b195efd356c3f2bbeccdb504102 second commit
../commits.bundle est correct

Si la personne avait crĂ©Ă© un colis ne contenant que les deux derniers commits qu’il avait ajoutĂ©s, plutĂŽt que les trois, le dĂ©pĂŽt initial n’aurait pas pu l’importer, car il aurait manquĂ© un commit dans l’historique Ă  reconstituer. La commande verify aurait ressemblĂ© plutĂŽt Ă  ceci :

$ git bundle verify ../commits-bad.bundle
error: Le dépÎt ne dispose pas des commits prérequis suivants :
error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 third commit - second repo

Cependant, notre premier colis est valide, et nous pouvons rĂ©cupĂ©rer des commits depuis celui-ci. Si vous souhaitez voir les branches prĂ©sentes dans le colis qui peuvent ĂȘtre importĂ©es, il y a aussi une commande pour donner la liste des sommets des branches :

$ git bundle list-heads ../commits.bundle
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master

La sous-commande verify vous indiquera aussi les sommets. L’objectif est de voir ce qui peut ĂȘtre tirĂ©, pour que vous puissiez utiliser les commandes fetch et pull pour importer des commits depuis le colis. Ici, nous allons rĂ©cupĂ©rer la branche master du colis dans une branche appelĂ©e other-master dans notre dĂ©pĂŽt :

$ git fetch ../commits.bundle master:other-master
Depuis ../commits.bundle
 * [nouvelle branche]      master     -> other-master

Maintenant, nous pouvons voir que nous avons importé les commits sur la branche other-master ainsi que tous les commits que nous avons validés entre-temps dans notre propre branche master.

$ git log --oneline --decorate --graph --all
* 8255d41 (HEAD, master) third commit - first repo
| * 71b84da (other-master) last commit - second repo
| * c99cf5b fourth commit - second repo
| * 7011d3d third commit - second repo
|/
* 9a466c5 second commit
* b1ec324 first commit

Ainsi, git bundle peut vraiment ĂȘtre utile pour partager du code ou rĂ©aliser des opĂ©rations nĂ©cessitant du rĂ©seau quand il n’y a pas de rĂ©seau ou de dĂ©pĂŽt partagĂ©.

scroll-to-top