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