Aspectos destacados de Git 2.31

Aspectos destacados de Git 2.31
Cambios de la nueva versión de Git 2.31. Imagen: Autoría de GITHUB.

El proyecto de código abierto de Git, ha lanzado la nueva versión de Git 2.31. Ahora, echemos un vistazo a los nuevos cambios y características más interesantes.

Introduciendo git maintenance

Imagínate esto: Estás en la terminal, escribiendo confirmaciones, extrayendo de otros repositorios y subiendo los resultados; de repente, recibes el siguiente mensaje:

El empaquetado automático del repositorio para un rendimiento óptimo; también puedes
ejecutar `git gc` manualmente. Consulte `git help gc` para obtener más información.

Si luego de ese mensaje, te encuentras atascado. Ahora tienes que esperar a que Git termine de ejecutar git gc --auto antes de poder volver al trabajo.

¿Qué es lo que ha pasado? En el curso del uso normal, Git escribe una gran cantidad de datos: Objetos, archivos de paquetes, referencias y similares.

Algunas de esas rutas, están optimizadas para el rendimiento de escritura. Por ejemplo, es mucho más rápido escribir un solo objeto «suelto», pero es más rápido leer un archivo de paquetes.

Para mantener la productividad, Git hace una compensación: en general, optimizando la ruta de escritura mientras estás trabajando.

Haciendo pausas de vez en cuando para representar sus estructuras de datos internas de una manera que sea más eficiente de leer con el fin de mantener su productividad a largo plazo.

Git, tiene sus propias heurísticas sobre cuándo es un buen momento para realizar esta «pausa», pero a veces, esas heurísticas desencadenan un bloqueo d git gc en el peor momento posible.

Puede administrar estas estructuras de datos, pero es posible que no desees invertir el tiempo en averiguar cómo y cuándo hacerlo.

A partir de Git 2.31, vas a poder obtener lo mejor de ambos mundos con el mantenimiento en segundo plano. Esta función multiplataforma permite a Git, mantener su repositorio en buen estado sin bloquear ninguna de sus interacciones.

En particular, esto mejorará sus tiempos de git fetch al obtener previamente los últimos objetos de sus controles remotos una vez cada hora.

Como comenzar con el mantenimiento en segundo plano: Simplemente navega a tu terminal, dentro de cualquier repositorio en el que desees habilitar el mantenimiento en segundo plano y ejecuta el siguiente comando:

$ git maintenance start

Git se encargará del resto. Además de precargar los últimos objetos una vez por hora, Git se asegurará de que sus propios datos también estén organizados.

Actualizará tu archivo commit-graph una vez cada hora y empacará cualquier objeto suelto (así como, volverá a empaquetar gradualmente los objetos ya empaquetados) todas las noches.

Puedes leer más sobre esta función de git maintenance en su documentación y aprender a personalizarla con las opciones de maintenance.* config.

Si tiene algún problema, puede consultar la documentación de solución de problemas de Git.

Índices inversos en disco

Es posible que sepas que Git almacena todos los datos como objetos: Confirmaciones, árboles y blobs que almacenan el contenido de archivos individuales.

Para mayor eficiencia, Git coloca muchos objetos en archivos de paquete, que son esencialmente un flujo de objetos concatenados (este mismo flujo es también cómo se transfieren los objetos por git fetch y git push).

Para acceder de manera eficiente a los objetos individuales, Git genera un índice para cada archivo de paquete.

Cada uno de estos archivos .idx permite la conversión rápida de un ID de objeto en su desplazamiento de bytes dentro del archivo de paquetes.

¿Qué pasa cuando quieres ir en la otra dirección? En particular, si todo lo que sabe Git es qué byte estás mirando en algún archivo de paquete, ¿Cómo se las arregla para averiguar de qué objeto forma parte ese byte?

Para lograr esto, Git usa un índice inverso con un nombre apropiado: Un mapeo opaco entre ubicaciones en un archivo de paquetes y el objeto del que forma parte cada ubicación.

Antes de Git 2.31, no existía un formato en disco para índices inversos (como existe para el archivo .idx) por lo que tenía que generar y almacenar el índice inverso en la memoria, una y otra vez.

Esto se reduce aproximadamente a generar una matriz de pares de posición de objeto y luego ordenar esa matriz por posición (para los curiosos, los detalles exactos se pueden encontrar aquí).

Pero esto lleva tiempo. En el caso de repositorios con grandes archivos de paquetes, esto puede llevar mucho tiempo.

Para comprender mejor la escala, considere un experimento que compare el tiempo que se tarda en imprimir el tamaño de un objeto con el tiempo que se tarda en imprimir el contenido de ese objeto.

Para imprimir simplemente el contenido de un objeto, Git usa el índice de avance para ubicar el objeto deseado en un paquete y luego vuelve a ensamblar e imprimir su contenido.

Pero para imprimir el tamaño de un objeto en un archivo de paquetes, Git necesita ubicar no solo el objeto que queremos medir, si no también el objeto que lo sigue inmediatamente; y luego, restar los dos, para averiguar cuánto espacio está usando.

Para encontrar la posición del primer byte en el objeto adyacente, Git necesita usar el índice inverso.

Comparando los dos, es más de 62 veces más lento imprimir el tamaño de un objeto que imprimir todo el contenido de ese objeto.

Puede probar esto en casa con «hyperfine» ejecutando:

$ git rev-parse HEAD >tip
$ hyperfine --warmup=3 \ 'git cat-file --batch <tip' \ 'git cat-file --batch-check="%(objectsize:disk)" <tip'

En 2.31, Git obtuvo la capacidad de serializar el índice inverso en un nuevo formato en disco con la extensón .rev.

Después de generar un índice inverso en el disco y repetir el experimento anterior, nuestros resultados ahora muestran que se necesita aproximadamente la misma cantidad de tiempo para imprimir el contenido de un objeto que su tamaño.

Los lectores observadores pueden preguntarse por qué Git incluso necesita molestarse en usar un índice inverso.

Después de todo, si puedes imprimir el contenido de un objeto, seguramente imprimir el tamaño de ese objeto no es más difícil que saber cuántos bytes escribió al imprimir el contenido.

Pero esto depende del tamaño del objeto. Si es enorme, entonces contar todos sus bytes es mucho más caro que simplemente restar.

Los índices inversos pueden ayudar más allá de experimentos sintéticos como estos: Cuando se envían objetos para una búsqueda o envío, el índice inverso se utiliza para enviar bytes de objetos directamente desde el disco.

Tener un índice inverso calculado con anticipación hace que este proceso se ejecute más rápido.

Git, todavía no genera archivos .rev de forma predeterminada, pero puedes experimentar con ellos ejecutando git config pack.writeReverseIndex true y luego re-empaquetando el repositorio (con git repack -Ad).

Lo hemos estado usando en GitHub durante los últimos meses para permitir mejoras drásticas en muchas operaciones diferentes de Git.

Tidbits

Commit-graph

Hemos hablado antes en este blog sobre el archivo commit-graph. Es una serialización increíblemente útil de información común sobre confirmaciones, como qué padres tienen, cuál es su árbol raíz, etc.

En Git 2.31, se utilizó un nuevo tipo de número de generación, que puede mejorar aún más el rendimiento en determinadas situaciones.

Correcciones en el HEAD a la hora de fusionar

En versiones recientes de Git, se ha vuelto más fácil cambiar el nombre predeterminado de la rama principal en un nuevo repositorio con la configuración init.defaultBranch Git siempre ha intentado verificar la rama en el HEAD de control remoto (es decir, si la rama predeterminada del control remoto era foo entonces git clone intentaba realizar foo localmente) pero esto no ha funcionado con repositorios vacíos.

En Git 2.31, esto ahora también funciona con repositorios vacíos. Ahora, si estás clonando un repositorio recién creado localmente para comenzar a escribir los primeros parches, su copia local respetará el nombre de rama predeterminado establecido por el control remoto; incluso si aún no hay confirmaciones.

Facilidad para cambiar nombres

Sobre el tema de cambiar el nombre de las cosas, Git 2.30 hace que sea más fácil cambiar el nombre por otro predeterminad.

El primer control remoto de un repositorio, cuando se crea a través de una clonación de otro repositorio mediante git clone hace que la primer rama se llame «origen» por defecto.

Antes de Git 2.30, sus opciones para cambiar el nombre se limitaban a la ejecución git remote rename origin <newname> con Git 2.30 se te va permitir configurar un nombre diferente que sea aportado por defecto; en lugar de usar siempre “origen”.

Para establecer el nuevo nombre por defecto, ejecuta en la configuración clone.defaultRemoteName.

Organizar mejor las ramas

Cuando un repositorio crece, puede ser difícil determinar qué ramas son las responsables. En Git 2.31 git rev-list
tiene una opción --disk-usage que es más simple y más rápida que usar, conjunto las herramientas existentes para resumir los tamaños de los objetos.

La sección de ejemplos del manual de rev-list muestra algunos usos (y puedes consultar el enlace de la fuente para conocer los tiempos y ver la forma «antigua» de hacerlo).

Mejoras en la búsqueda de cadenas

Es posible que haya usado la opción de Git -G<regex> para buscar confirmaciones que modificaron una línea que menciona una cadena en particular (por ejemplo, git log -G'foo\(' buscará cambios que se agregaron, eliminaron o modificaron llamadas a la función foo()).

Pero es posible que también desee ignorar las líneas que coinciden con un patrón determinado.

En Git 2.30, se introduce -I<regex> que te permite ignorar los cambios en las líneas que coinciden con una expresión regular. Por ejemplo, git log -p -I'//' mostraría el parche para cada confirmación, pero omitiría cualquier trozo que solo toque las líneas de comentarios (las que contienen //).

Optimizar las fusiones

En preparación para reemplazar el backend de fusión, la detección de cambio de nombre se ha optimizado sustancialmente. Puede leer más sobre estos cambios de su autor en Optimización de la maquinaria de fusión de git, #1 y Optimización de la maquinaria de fusión de git, #2.

Fuente: Blog Oficial de Github

ROSEPAC

Redactor Diario Ciberninjas. Curador Digital. 🔗 Telegram 👨‍💻 Twittter 🐦 Discord 🧰