Git
Chapters ▾ 2nd Edition

7.12 Herramientas de Git - Agrupaciones

Agrupaciones

Aunque ya hemos considerado las maneras más comunes de transferir la base de datos de Git en el Internet (HTTP, SSH, etc.), existe aún otra manera de hacerlo, que aunque no es muy comúnmente usada puede ser muy útil.

Git es capaz de “agrupar” la base de datos en un único archivo. Esto puede ser muy útil en varios escenarios. Tal vez tu red está caída y quieres enviar cambios a tus co-trabajdores. Quizas estás trabajando en algún lugar sin conexión y no tienes acceso a la red local por motivos de seguridad. Tal vez tu tarjeta inalámbrica / ethernet se rompió. Tal vez no tienes acceso al servidor compartido por el momento, y quieres enviar un correo con actualizaciones y no quieres transferir 40 confirmaciones via format-patch.

Aquí es donde el comando de git bundle es muy útil. El comando bundle juntará todo, lo que normalmente se empujaría sobre el cable con un comando git push, en un archivo binario que puedes enviar por correo a alguien o poner en un flash drive, y luego desglosarlo en otro repositorio.

Veamos un ejemplo simple. Digamos que tienes un repositorio con dos confirmaciones:

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

    Segunda Confirmacion

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

    Primera confirmación

Si quieres enviar ese repositorio a alguien y no tienes acceso a algún repositorio para hacerlo, o simplemente no quieres configurar uno, puedes juntarlo con el `git bundle create `.

$ git bundle create repo.bundle HEAD master
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 441 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)

Ahora tienes un archivo nombrado repo.bundle, éste tiene todos los datos nuevos necesarios para re-crear el repositorio de la rama maester. Con el comando bundle necesitarás enlistar cualquier referencia o rango específico de confirmaciones que quieras que sean incluidas. Si tienes la intención de clonar esto en otro lugar, debes agregar HEAD como referencia, así como lo hemos hecho aquí.

Puedes enviar por correo este archivo repo.bundle a alguien más, o ponerlo en una memoria USB y simplemente irte.

Por otro lado, supongamos que se envía este archivo de repo.bundle y deseas trabajar en el proyecto. Puedes clonarlo desde el archivo binario en un directorio, como lo harías desde una 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 no quieres incluir HEAD en las referencias, también tendrás que especificar -b master o cualquier rama que sea incluída porque de otra manera Git no sabrá que rama revisar.

Digamos que ahora haces tres confirmaciones y quieres enviar nuevas confirmaciones vía agrupación en una USB o por correo.

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

Primero necesitamos determinar el rango de confirmaciones que queremos incluir en la agrupación. No es como en los protocolos de la red donde figurará el mínimo de datos para transferir desde la red por nosotros, tendremos que hacer esto manualmente. Ahora simplemente puedes hacer la misma cosa y agrupar el repositorio entero, el que trabajará, pero es mejor sólo agrupar las diferencias – solamente las tres confirmaciones que hicimos localmente.

Para hacer eso, tienes que calcular la diferencia. Como hemos descrito en Rangos de Commits, Puedes especificar el rango de confirmaciones en un numero de caminos. Para obtener las tres confirmaciones que tenemos en nuestra rama maestra que no estaban en la rama que copiamos originalmente, podemos usar algo como origin/master..master o master ^origin/master. Puedes probar esto con el comando log.

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

Entonces ahora que tenemos la lista de confirmaciones, queremos incluirlas en la agrupación, agrupémoslas todas. Hacemos eso con el comando git bundle create, dándole un nombre al archivo que queremos que sea parte de la agrupación y el rango de confirmaciones que queremos incluir en el mismo.

$ git bundle create commits.bundle master ^9a466c5
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), 775 bytes, done.
Total 9 (delta 0), reused 0 (delta 0)

Ahora tenemos un archivo de commits.bundle en nuestro directorio. Si tomamos éste y se lo enviamos a nuestro compañero, puede importarlo en el repositorio original, aún si se ha incluido más trabajo en el tiempo que ha pasado.

Cuando obtenga la agrupación, puede inspeccionarlo para ver qué contiene antes de que lo importe en el repositorio. El primer comando es el bundle verify que te hará saber si el archivo es actualmente una agrupación válida de Git y así tendrás todos los requerimientos necesarios para reconstituirlo apropiadamente.

$ git bundle verify ../commits.bundle
The bundle contains 1 ref
71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master
The bundle requires these 1 ref
9a466c572fe88b195efd356c3f2bbeccdb504102 second commit
../commits.bundle is okay

Si el agrupador ha creado una agrupación de sólo las dos últimas confirmaciones que se han hecho, en lugar de las tres, el repositorio original no será capaz de improtarlo, dado que falta un requisito en la historia. El comando de verify debería de verse entonces así:

$ git bundle verify ../commits-bad.bundle
error: Repository lacks these prerequisite commits:
error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 third commit - second repo

Como sea, nuestra primera agrupación es válida, entonces podemos obtener confirmaciones de ella. Si quieres ver qué ramas que están en la agrupación pueden ser importadas, hay un comando para verlo:

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

El sub-comando de verify te dirá el encabezado también. El punto es ver qué puede ser puesto, para que puedas usar el comando de fetch fetch o pull para importar confirmaciones de este archivo. Aquí vamos a buscar la rama master de la agrupación con una llamada other-master en nuestro repositorio:

$ git fetch ../commits.bundle master:other-master
From ../commits.bundle
 * [new branch]      master     -> other-master

Ahora podemos ver que hemos importado las confirmaciones a la rama de other-master, así como tantas confirmaciones hayamos hecho mientras tanto en nuestra rama 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

Entonces, git bundle puede ser muy útil para compartir o hacer operaciones tipo red cuando no tienes la red adecuada o repositorio compartido para hacerlo.