Git es una potente herramienta para el control de versiones y tiene una especie de monopolio en este ámbito. Para la mayoría de las tareas cotidianas, Git puede ser sencillo de utilizar gracias a su repetición de comandos. Sin embargo, hay muchas situaciones en las que necesitas algo más que lo básico. Por ello, existen un montón de comandos avanzados de Git que pueden llevar tus habilidades de Git al siguiente nivel.
Esto también te introducirá en varios conceptos de Git con los que normalmente no te encontrarías. Por ejemplo, almacenar temporalmente en lugar de confirmar cambios, volver a basar y añadir archivos a tu staging area. Una vez que los aprendas, puede que descubras que tienes un valor aún mayor para tu equipo.
En esta entrada del blog, introduciremos los distintos commandos avanzados que querrás conocer. Sin embargo, para utilizarlos, necesitas tener a mano algunas habilidades, conceptos e información. Veamos esto primero.
Requisitos Previos Recomendados
Aunque seas capaz de aprender lo básico de Git y entender algunos de los comandos intermedios, como git delete
, necesitas más habilidades para manejar los comandos avanzados.
Los consejos que compartimos aquí no serán adecuados para un principiante en Git, así que si el control de versiones, en general, es nuevo para ti, te recomendamos que pases algún tiempo utilizando los comandos básicos a diario antes de buscar añadir más cosas a tu repertorio.
En resumen, aquí tienes una lista rápida de los aspectos que debes comprender:
- Conceptos básicos de Git como commits, branches, pull requests, etc.
- Familiaridad con comandos básicos de Git como
git add
,git merge
,git commit
, ygit push
. - Para las tareas avanzadas de Git, necesitas ser capaz de navegar por un Terminal.
Es útil tener experiencia trabajando con Git en un entorno de equipo, ya que muchos de estos comandos pueden tener un impacto significativo en una base de códigos compartida. Por ejemplo, puede ser que sólo utilices algunos de estos comandos en un puesto de responsabilidad. Esto significa que debes tener cuidado y saber cuándo utilizas estos comandos.
Git Avanzado: 12 Comandos Poderosos que Querrás Conocer
El resto de este artículo cubrirá 12 comandos Git avanzados diferentes que te llevarán más allá de lo básico y te convertirán en un mago de Git. Empecemos con un comando que puede que utilices más que otros.
1. Rebasing
En primer lugar, rebasing es un potente comando de Git que es una alternativa a una solicitud de extracción. Te permite arrastrar todos los nuevos commits que hagas tras una divergencia de rama a una nueva rama y ranurar los cambios en la punta de la base. Esto te resultará útil si quieres incorporar cambios de otra rama sin crear un commit de fusión por el motivo que sea.
Un caso de uso común para el rebasing es cuando estás trabajando en una rama de características y quieres incorporar cambios de la rama principal sin crear una confirmación de fusión. Ayuda a mantener limpio el historial de tu proyecto, aunque puede tardar más en ejecutarse y puedes ver más errores durante una fusión.
Para volver a basar una rama, utiliza el comando git rebase
. Aquí tienes un ejemplo en el que estamos fusionando una rama con otra:
git checkout foo-branch
git rebase main
También puedes listar los commits que vas a liberar y darte la oportunidad de editarlos de antemano. Así, puedes combinar commits, editar mensajes de commit, etc. Puedes utilizar la bandera --interactive
o --i
para realizar un ‘rebase interactivo’
git rebase --interactive <other-branch-name>
Hablando de eso, combinar confirmaciones en una sola para ordenar un historial de confirmaciones es un caso de uso común para el rebase. Esto puede hacer que tu historial de confirmaciones sea más fácil de leer y entender.
Para hacer esto durante un rebase, sigue la bandera con el número de confirmaciones que te gustaría combinar, lo que combinará las confirmaciones en una sola:
git rebase -i HEAD~3
Esto abrirá una ventana interactiva de revisión, muy parecida a la ventana de confirmaciones, donde puedes elegir y editar las confirmaciones que quieres eliminar:
Tienes una lista de confirmaciones en la parte superior de la pantalla y una selección de comandos en la parte inferior, junto con alguna otra información relevante. La opción por defecto es pick
un commit, que lo selecciona como el que quieres utilizar sin cambios.
Sin embargo, hay muchos otros comandos que te ayudarán a navegar por un rebase. Por ejemplo, puedes reformular un commit o combinar varios commits juntos. Para hacer cambios y utilizar los comandos, trabajarás con el editor de tu Terminal. El predeterminado suele ser Vim, lo que significa que necesitas conocer ese editor.
El último paso es guardar tus cambios y luego enviarlos a la rama remota.
2. Reverting, Resetting y Unstaging
Git tiene mala fama cuando se trata de deshacer cambios. Es un proceso difícil en general, con tendencia a generar errores. Sin embargo, si haces cambios en tu directorio de trabajo o en tu área de staging que quieres deshacer, hay algunos comandos de Git que pueden ayudarte.
De hecho, Git te orienta sobre cómo deshacer un archivo si ejecutas un comando git status
:
De este modo, puedes eliminar una confirmación de la rama actual y enviarla a otro lugar con facilidad:
git reset HEAD <commit>
Esto tiene el efecto de hacer retroceder tu rama una confirmación, como si eliminaras la última confirmación conocida. Incluso puedes tener un caso de uso en el que quieras restablecer una rama a su estado original. En este caso, puedes restablecer contra el origen remoto, por ejemplo, utilizando git reset --hard origin/main
. Sin embargo, ten en cuenta que estos cambios desaparecerán para siempre.
Aunque el comando git checkout
es uno de los que utilizarás a menudo y se considera básico, también puedes utilizarlo para deshacer archivos antes de una confirmación:
git checkout -- <filename>
Observa el espacio entre los guiones y el nombre del archivo. Aquí, el comando deshace el archivo que especifiques y descarta los cambios del directorio de trabajo. Ten en cuenta que esto borrará cualquier cambio local que hagas en un archivo. Por ello, comprueba dos y tres veces que no necesitas esos cambios no guardados.
También puedes utilizar git revert
los cambios que hagas en una confirmación. Sin embargo, esto no deshace los cambios, sino que crea una nueva confirmación basada en deshacer los cambios dentro de la anterior.
La principal diferencia aquí es que el comando no moverá ningún puntero de referencia a la nueva confirmación, sino que mantendrá las confirmaciones antiguas. Esto es útil cuando quieres deshacer cambios sin eliminarlos de tu historial de confirmaciones.
El comando espera recibir una referencia, y es sencillo revertir la última confirmación:
git revert HEAD
Sin embargo, tienes mucho más margen para restaurar y modificar archivos y confirmaciones. Las dos próximas entradas de esta lista de comandos avanzados de Git se ocuparán de ellas.
3. Restauración archivos a su estado por defecto
Con Git, puedes restaurar fácilmente un archivo a su estado por defecto utilizando un comando bastante nuevo: git restore
. De hecho, deberías considerarlo un sustituto de git reset
en la mayoría de las circunstancias, ya que ofrece mucha más potencia bajo el capó. Por ejemplo, puedes conseguir el mismo resultado con git restore --staged <filename>
que con git reset HEAD
.
Sin embargo, el comando puede hacer más cosas: también puede restaurar archivos a sus estados predeterminados. Puedes ver cómo hacerlo si ejecutas también git status
:
git restore <filename>
Esto eliminará los cambios del directorio de trabajo como si no hubiera pasado nada. Al igual que con git checkout -- <filename>
, debes asegurarte de que no quieres ninguno de los cambios locales, ya que desaparecerán para siempre.
4. Modificación de confirmaciones
Probablemente habrá muchas ocasiones en las que envíes una confirmación y te des cuenta de que has olvidado incluir algo importante. Con Git, puedes modificar fácilmente la confirmación para incluir los cambios que faltan.
Para ello sigue un proceso específico:
- Primero, haz los cambios en los archivos que necesites para el proyecto.
- Prepáralos como es habitual utilizando
git add
. - Vuelve a confirmar esos cambios en el área de preparación utilizando un comando diferente para realizar la confirmación:
git commit --amend
Esto modifica el commit original con el nuevo utilizando tu área de staging para ello. Por tanto, asegúrate de que no necesitas la versión antigua del commit, ya que se perderá. También te recomendamos que utilices la bandera --amend
con commits locales en lugar de remotos, por razones similares a las que tratamos en otra parte de este post.
También puedes utilizar git commit --amend
para editar sólo el mensaje de confirmación con el siguiente comando:
git commit --amend -m "New commit message"
5. Registro de Git
Utilizar el registro de Git es valioso para ayudarte a comprender el historial de un repositorio. Sin embargo, no clasificaríamos el comando git log
como avanzado. En su lugar, puedes utilizar varias opciones para filtrar la salida según tus necesidades:
git log
git log --decorate
git log --stat
Por ejemplo, al decorar una entrada del registro se imprimen los nombres de referencia de todas las confirmaciones mostradas. La opción --stat
muestra las inserciones y eliminaciones de una confirmación:
También puedes utilizar otras opciones para personalizar la salida del registro, lo que se denomina «limitación de confirmaciones» Por ejemplo, toma los siguientes comandos:
git log --author=<author-name>
git log --grep=<pattern-string>
Aquí puedes filtrar el registro por nombres de autor o patrones de texto específicos. De hecho, puedes combinar varias opciones y banderas para generar un registro con un propósito específico. Por ejemplo, toma este comando:
git log --oneline --author=<author-name> --since=<date> feature-temp
Busca todos los commits con la rama feature-temp de un autor singular desde una fecha especificada, y luego imprímelos utilizando entradas de una sola línea. Ten en cuenta que el parámetro <date>
también puede ser una cadena:
--since=”Two weeks ago”
Además, si quieres buscar un archivo concreto en lugar de una rama, puedes ejecutar
git log --oneline --author=bartonfink --since=”5 days ago” -- readme.rm
Este conjunto de ejemplos sólo roza la superficie de lo que puedes hacer con tus registros, pero hay mucho margen para encontrar commits exactos en ellos en función de tus criterios de búsqueda.
6. Hooks Git
Es probable que a veces utilices macros y otros scripts automatizados para ayudar a ejecutar código. Git también incluye este tipo de funcionalidad en forma de ganchos. Estos scripts se ejecutan automáticamente en respuesta a determinados eventos, como confirmaciones o envíos. También hay muchas formas de utilizar ganchos para aplicar formato al código, ejecutar pruebas y mucho más.
Hay dos tipos de ganchos: del lado del cliente y del lado del servidor:
- Los ganchos del lado del cliente se activan basándose en acciones locales como confirmaciones y fusiones.
- Los ganchos del lado del servidor se activarán debido a operaciones de red. Por ejemplo, cuando un repositorio recibe una confirmación enviada, entre otros muchos ejemplos.
Git siempre rellenará tu repositorio con varios ganchos de ejemplo una vez que ejecutes un git init
. Sin embargo, debes eliminar la extensión .sample para poder utilizarlos:
Ten en cuenta que sólo puedes ejecutar un tipo de gancho a la vez, aunque es posible utilizar varios scripts a la vez con un poco de trabajo. Por ello, los nombres de tus archivos deben corresponder al tipo de gancho que quieras utilizar basándote en los scripts de ejemplo: pre-commit, update, etc.
Crear un hook Git
Para crear un gancho Git, necesitas crear un script ejecutable en el subdirectorio .git/hooks sin extensión. Seguirá ejecutándose siempre que lo añadas a la carpeta hooks.
Puedes utilizar cualquier lenguaje de programación que desees, siempre que pueda ejecutarse como un ejecutable. Te sugerimos Ruby o Python, pero puedes utilizar Bash, Perl y muchos otros. Todo lo que tienes que hacer aquí es cambiar la ruta a tu intérprete desde la predeterminada de Bash:
#!/usr/bin/env python
A partir de aquí, puedes escribir tu código con normalidad. Por ejemplo, aquí tienes un script prepare-commit
en Python que pide al usuario que escriba buenos mensajes de confirmación:
#!/usr/bin/env python
import sys, os
path_commit_msg = sys.argv[1]
with open(commit_msg_filepath, 'w') as f:
f.write("# You’ll need to provide a better commit message than that, buddy!")
Aunque no siempre es necesario, te recomendamos que ejecutes chmod +x .git/hooks/<hook-name>
desde la línea de comandos para asegurarte de que puedes ejecutarlo.
En general, los ganchos pueden ser una herramienta poderosa para automatizar tareas repetitivas e imponer las mejores prácticas dentro de tu equipo.
7. Referencias de commits
En Git, identificas los commits por el hash decifrado SHA-1. Aunque es posible referirse a los commits por su hash completo, esto puede ser tedioso y propenso a errores:
bc7623b7a94ed3d8feaffaf7580df3eca4f5f5ca
En su lugar, Git proporciona varias formas de referirse a las confirmaciones utilizando nombres más cortos y memorables. Por ejemplo, puedes utilizar un nombre de rama o etiqueta. Por ejemplo, considera una rama llamada «desarrollar». Aquí tienes un ejemplo en el que nos referimos a la última confirmación de esta rama:
git diff develop..HEAD
Esto muestra las diferencias entre la última confirmación (HEAD
) en la rama «desarrollar» y la confirmación actual.
También puedes referirte a una confirmación por su posición relativa en el historial de confirmaciones. Por ejemplo, puedes referirte a dos confirmaciones anteriores a la actual utilizando la abreviatura HEAD~2
:
git diff HEAD~2..HEAD
Git también proporciona otras formas de referirse a las confirmaciones, como utilizar el símbolo «@» para referirse a la rama actual o utilizar el símbolo «^» para referirse al padre de una confirmación. Utilizando estas notaciones abreviadas, puedes ahorrar tiempo y evitar errores al trabajar con confirmaciones.
8. Stashing
En circunstancias normales, pensarías que no hay forma de almacenar los cambios que haces en los archivos sin confirmarlos. «Stashing» es la forma de guardado provisional de cambios. Es útil cuando necesitas cambiar de rama o trabajar en una tarea diferente, pero no quieres confirmar tus cambios todavía.
Por ejemplo, si necesitas cambiar de rama para trabajar en algo a mitad del flujo, puedes almacenar los cambios en la rama actual y hacer checkout en la otra. Desde ahí, puedes trabajar en la otra rama, luego confirmar y enviar esos cambios. Luego puedes hacer checkout y recuperar tu trabajo en la rama original.
Para almacenar cambios hay dos formas de hacerlo:
git stash
Esto almacena tus cambios en un nuevo stash, y revierte tu directorio de trabajo a la última confirmación HEAD (el estado en que lo tenías antes de hacer nuevos cambios). Puedes listar los cambios utilizando git stash list
, e inspeccionar el alijo utilizando git stash show
. Este último comando también puede aceptar cualquier formato que acepte git diff
.
Desde aquí, puedes cambiar de rama o trabajar en una tarea diferente. Cuando quieras recuperar tus cambios, ejecuta el siguiente comando:
git stash apply
Esto aplicará los últimos cambios almacenados a tu directorio de trabajo. Sin embargo, ten en cuenta que aún puedes encontrarte con conflictos si cambias demasiado el archivo. Al fin y al cabo, git stash
es una solución temporal al problema en cuestión.
También puedes tener varios stashes, y puedes especificar qué stash aplicar utilizando lo siguiente:
git stash apply stash@{n}
El marcador de posición {n}
toma un número entero, y stash@{0}
representa el último alijo. La documentación oficial de Git incluye otros ejemplos de git stash
.
9. Bisecting
Apostaríamos a que todo el mundo se ha encontrado alguna vez con un error o un problema y no tenía ni idea de por dónde empezar a buscar la solución. En estas situaciones, «bisecar» puede ayudarte a identificar rápidamente la confirmación que introdujo el problema.
En pocas palabras, el comando busca errores mediante una búsqueda en tus confirmaciones. Una vez que encuentra el commit infractor, te lo devuelve. La potencia de este comando reside en todos los subcomandos que puedes utilizar.
Para utilizar bisecting, primero tienes que ejecutar el comando git bisect start
. Git te llevará al primer commit del historial de tu proyecto.
A partir de aquí, tienes que indicar si ese commit es bueno o malo utilizando los comandos pertinentes:
git bisect good
git bisect bad
Git te llevará entonces al siguiente commit para comprobar su «calidad» Ten en cuenta que también puedes sustituir «good» por «old» y «bad» por «new» para ajustarlo a tu caso de uso específico (aunque no puedes mezclar términos)
A partir de aquí, puedes seguir marcando cada confirmación como buena o mala hasta que encuentres la confirmación que introdujo el error. Sin embargo, no tienes que rastrear todas las confirmaciones: puedes especificar identificadores exactos que te ayuden a acotar y acortar tu búsqueda:
git bisect bad feature-test
En este caso, se utiliza un nombre de rama, pero podría ser una revisión específica utilizando un número entero, una referencia hash, etc. En cualquier caso, una vez que caces y encuentres el fallo, puedes ejecutar cualquiera de los siguientes comandos para volver a tu código más reciente:
git bisect reset
Como con todos los comandos avanzados de Git de esta lista, hay mucho más que digerir, y la documentación de Git será una lectura esencial en este caso.
10. Comparar las ramas
Nuestra entrada sobre referencias de confirmaciones habla sobre el uso de git diff
. Ahora es el momento de ver esto con más detalle. A menudo te encontrarás con varias ramas que contienen cambios diferentes. Git te permite comparar las diferencias entre dos ramas utilizando el comando git diff
. De hecho, puedes utilizarlo de varias formas, a menudo junto con otros comandos, para investigar y analizar un repositorio.
El comando básico git diff
te dará una salida con una visión general de los cambios. Se parece mucho a la salida de una investigación de fusión de confirmaciones:
Sin embargo, puedes profundizar en ramas exactas, hashes y muchos más. Por ejemplo, para comparar dos ramas, ejecuta el comando git diff branch1..branch2
y sustituye los marcadores de posición:
git diff feature-branch pre-prod
También puedes comparar las diferencias entre tu rama actual y otra rama:
git diff HEAD..pre-prod
Ten en cuenta que utilizar dos puntos aquí devolverá la diferencia entre las dos puntas de las ramas. En cambio, tres puntos devolverán la diferencia entre el ancestro común de ambas ramas y lo utilizarán para hacer la prueba.
Al igual que git log
, puedes limpiar la salida y refinar lo que devuelve. Por ejemplo, git diff --name-only branch1..branch2
sólo comprobará qué archivos difieren y omitirá el contexto:
Puede que encuentres que la salida es difícil de analizar, especialmente si el «diff» es largo. En estos casos, puedes utilizar la opción --color-words
:
En general, git diff
puede ser tan potente como otros comandos, especialmente cuando invocas ciertas opciones y refinas qué diferencias devuelve.
11. Aplicar commits individuales
A veces puedes querer aplicar un commit específico de una rama a otra sin fusionar las dos ramas. Git te permite hacerlo utilizando git cherry-pick
. Debes utilizarlo con cuidado, pero puedes encontrar que git cherry-pick
puede ayudarte en algunos escenarios.
Una situación es cuando tienes ramas de características obsoletas que no fusionas en main
o trunk
. Podrías utilizar una combinación de comandos (como git log
) para desenterrar antiguos commits relevantes y volver a aplicarlos en otro lugar.
Utiliza git log para encontrar la referencia de un commit. A partir de ahí, asegúrate de que estás en la rama a la que te gustaría hacer cherry pick de una referencia. Por ejemplo, supongamos que quieres hacer cherry-pick del commit xxxxxaaaaaa
en la rama «trunk
«. Primero, comprueba tu rama..
git checkout trunk
…y luego selecciona tu commit:
git cherry-pick xxxxxaaaaaa
Es probable que tu mensaje de confirmación no esté actualizado en muchas ocasiones. Para solucionarlo, puedes pasar la opción --edit
al comando. Esto te permitirá proporcionar un nuevo mensaje de confirmación antes de la selección.
12. Potenciando ‘git add’
Para nuestro último comando avanzado de Git, vamos a mostrarte git add
. No, no es una errata: este comando fundamental de Git tiene un poder sorprendente bajo su capó.
Por ejemplo, si te encuentras añadiendo archivos individuales al área de preparación, puedes utilizar lo siguiente:
git add -p
La opción -p
te permite organizar los cambios de forma interactiva. Puedes revisar los cambios que has hecho en cada archivo y luego elegir los que vas a preparar. Esto podría ahorrarte mucho tiempo y ayudarte a evitar escenificar un cambio no deseado.
Aunque ya sabes que puedes organizar archivos individuales, también puedes especificar un directorio. Por ejemplo, para escenificar todos los archivos del directorio «new-feature
«:
git add new-feature
Puede que incluso quieras ver cuál será el resultado de un git add
sin llevar a cabo el proceso en su totalidad. Tienes una opción para ello:
git add --dry-run
git add -n
Cuando lo ejecutes, Git te mostrará si añadirá o ignorará los archivos. Hablando de archivos ignorados, también puedes añadirlos al área de preparación si lo deseas:
git add --force
git add -f
Añadir archivos al área de preparación puede ser más complejo que un simple escenario binario de «Añadir o no añadir». Como tal, uno de los comandos más básicos de Git puede cubrir una miríada de eventualidades.
Resumen
Una vez que tengas los comandos básicos de Git en el bolsillo, tendrás el 80 por ciento de lo que necesitas para llevar a cabo las tareas habituales de control de versiones de tu proyecto. Sin embargo, en el 20 por ciento final es donde pueden brillar los comandos avanzados de Git.
Comandos y técnicas como rebasing, bisecting, restaurar archivos, etc., te sacarán rápidamente de un apuro. Y lo que es más, puedes ofrecer un mayor valor a tu equipo y a tu proyecto, y podrías ayudar a agilizar los flujos de trabajo, aumentar la productividad y tener, en general, un mayor efecto como desarrollador.
¿Alguno de estos comandos avanzados de Git formará parte de tu trabajo diario? ¡Háznoslo saber en la sección de comentarios más abajo!
Deja una respuesta