Comandos de Git
Como dijimos, Git es una herramienta de línea de comandos, por lo tanto, vamos a ver los comandos básicos que ejecutan todas las funcionalidades que venimos describiendo.
Todos los comandos de Git comienzan con el nombre del programa git
, seguido del (sub) comando que queremos ejecutar, conocidos como comandos git o verbos. La sintaxis es, en general, la siguiente:
1git [opciones] <comando> [argumentos]
Los ejemplos que mostraremos a continuación están ejecutados en Git Bash.
git init
Este comando se utiliza una sola vez para inicializar un repositorio y, por tanto, para que Git comience a trackear los archivos.
1git init
Si, al momento de instalar Git, dejamos la configuración por defecto, se usará master
como nombre de la rama inicial.
De todas formas, si queremos cambiarlo a main
, todavía podemos hacerlo, al momento de ejecutar git init
, agregando la opción --initial-branch=<nombre>
.
1git init --initial-branch=main
O su versión corta:
1git init -b main
git status
Este comando, como ya vimos, sirve para ver en qué estado está el repositorio. Este nos mostrará:
- En qué branch nos encontramos, y si estamos adelantados y/o retrasados respecto de la branch ligada (si la hay) en el repositorio remoto configurado (si lo hay).
- Si hay archivos nuevos, modificados o eliminados.
- Cuáles archivos están en el área de staging y, si no hay ninguno, informará que no hay nada para guardar.
1git status
Si agregamos la opción -s
obtendremos una salida resumida.
1git status -s
git add (archivo | lista de archivos | opción)
Este comando sirve para agregar uno o más archivos al área de staging.
El o los archivos a agregar deben ser nuevos archivos (en estado untracked) o archivos que ya se estaban trackeando y que hayan sido modificados o eliminados.
Para marcar uno o varios archivos hay que indicarlos después del comando add
, separados por un espacio en blanco, por ejemplo:
1git add main.py data.py
Si queremos marcar todos los archivos del repositorio que fueron agregados, modificados o eliminados, debemos usar la opción -A
o --all
:
1git add -A
También es posible indicar patrones glob (incluidos en el shell, no son parte de Git), como, por ejemplo:
1git add *.py
Indica todos los archivos, con cualquier nombre, pero terminados en .py
. Solo los archivos que cumplan el patrón serán tenidos en cuenta.
1git add ui-*.xml
Indica todos los archivos cuyos nombres comiencen con ui-
y terminen en .xml
. Los archivos que no cumplan con el patrón no serán tenidos en cuenta.
1git add .
Este último ejemplo indica todos los archivos presentes en el directorio actual. El patrón glob y el indicador de ruta relativa .
, actúan en relación al directorio actual en el que se ejecuta el comando. Por lo tanto, si estamos en un subdirectorio del directorio principal del proyecto, solo se tendrán en cuenta los cambios en ese subdirectorio. Si hay cambios a la altura el directorio principal, estos no serán tenidos en cuenta.
Por esto es que, si deseamos agregar todos los cambios realizados, se recomienda usar la primera opción git add -A
.
Relacionado con este comando, tenemos al comando git restore --staged <archivo>
. Que sirve para sacar del área de staging a un archivo que se haya añadido con el comando git add
.
1git restore --staged main.py
Esto quitará los cambios del archivo main.py
del área de staging, y este volverá a figurar como modified o untracked según corresponda.
En realidad, el comando restore
tiene muchos más usos, pero los veremos en otro momento.
git commit
Sirve para “confirmar” (guardar) permanentemente en el repositorio los cambios agregados previamente al área de staging. A este comando es recomendable siempre agregarle la opción -m
seguida de un mensaje escrito entre comillas, con una explicación de los cambios realizados.
Por ejemplo:
1git commit -m "Modificado acceso a base de datos."
git branch <nombre>
Crea una nueva branch en el repositorio local, asignándole el nombre indicado como argumento.
Esta operación solo crea la nueva branch, si queremos movernos a ella debemos usar git checkout
o git switch
.
La branch que se crea tendrá un estado exactamente igual al de la branch sobre la cual hayamos ejecutado el comando git branch
. Es decir, se creará a partir del último commit de la branch actual.
Las branches pueden servir para un tracking largo, para branches de desarrollo como main
o development
, o para trackings cortos, como branches que resuelven bugs o issues (veremos qué son más adelante).
Sin importar el fin, la branch debe tener un nombre:
1git branch development
1git branch bugfix-1234
También es posible mostrar todas las branches existentes en el repositorio con la opción -a
.
1git branch -a
O mostrar solo las branches remotas, con -r
.
1git branch -r
Para eliminar una branch tenemos que utilizar la opción -d
o --delete
y el nombre de la branch a eliminar.
1git branch -d bugfix-1234-login
Eliminar una branch es usual cuando se completa la funcionalidad para la cual se creó la branch. Sobre todo para branches que resuelven bugs.
git switch <nombre>
- git checkout <nombre>
Cambia de la branch actual a la branch con el nombre indicado como argumento. Es decir, cambia el contexto en el cual se encuentra el usuario, al de la branch elegida.
Para poder movernos de branch no debe haber cambios sin guardar de archivos que ya están siendo trackeados en la branch actual (ya sean cambios en el directorio de trabajo o cambios en el área de staging). Si estos existen, Git no nos dejará movernos, y vamos a tener que guardarlos con un commit antes de poder realizar el cambio.
Por otro lado, si en la branch actual existen solo archivos nuevos, ya sea que estén en estado untracked o staged, al realizar el switch
estos se moverán a la branch indicada, ya que no estaban siendo trackeados en la branch actual.
El comando switch
está disponible en Git desde la versión 2.23.
1git switch development
1git checkout testing
También es posible crear una branch y moverse a ella en un mismo comando, usando la opción -c
con switch
(la cual es la versión corta de --create
) o -b
con checkout
. Por ejemplo:
1git switch -c development
1git checkout -b testing
Con switch
también podemos volver a la branch anterior usando simplemente -
. Por ejemplo:
1git switch -
git clone <URL>
Sirve para descargar un repositorio remoto ubicado en una plataforma online a nuestra PC. Se conoce como clonar o copiar.
Crea un nuevo directorio dentro del directorio actual en donde se ejecuta el comando y descarga el directorio oculto .git
.
Configura al repositorio remoto (del cual hacemos el clone) como el repositorio remoto origin
(nombre por defecto, que se puede cambiar) del repositorio local.
Además, crea branches locales para cada branch del repositorio. Cada una de estas branches está ligada con su correspondiente branch remota.
Finalmente, realiza el checkout de la branch activa (usualmente main
) al directorio de trabajo. Dejando el directorio listo para que el desarrollador trabaje en el proyecto.
La URL del repositorio debe ser obtenida de la plataforma online que mantiene el proyecto.
Por ejemplo, usando un repositorio público en GitHub:
Si el repositorio es público, no se pedirá ninguna autenticación al ejecutar el comando clone.
Por otro lado, si es privado, solo colaboradores asignados al repositorio pueden clonarlo. En tal caso, al ejecutar el comando se pedirá la autenticación del usuario (de la plataforma).
La URL puede usar distintos protocolos: ssh, https y otros. Cada protocolo tiene su manera de autenticar al usuario en la plataforma para permitir la descarga.
Para usar SSH se debe autenticar con una clave ssh pública propia que debe estar configurada la cuenta de usuario de la plataforma del desarrollador.
Por otro lado, HTTPS usualmente solicita autenticación mediante un navegador web. Alternativamente, se puede autenticar mediante un token generado en la plataforma.
El comando debe ejecutarse con la URL, como se muestra a continuación:
1git clone https://github.com/academiacimneiber/todo_app.git
Git mostrará una salida con los detalles de la descarga.
Observar que nos encontramos en el directorio git-ejemplos/
al momento de ejecutar el comando, por lo tanto, el repositorio creará un nuevo directorio llamado, en este caso, todo_app/
adentro de este para copiar allí el repositorio.
Después de ejecutar el comando obtendremos un directorio de trabajo trackeado por Git y cuyas branches locales están ligadas a sus respectivas branches remotas.
git push <remote> <branch>
Este comando sirve para subir uno o más commits de una branch local a una branch de un repositorio remoto.
Una vez que hayamos guardado cambios de forma local, con uno o más commits, podemos sincronizar estos cambios con un repositorio remoto.
En general, siempre vamos a subir los cambios de una branch local a su correspondiente branch en el repositorio remoto, aunque se puede hacerlo hacia cualquiera de ellas.
Por ejemplo, si tenemos una branch local development
(y estamos ubicados en ella), la cual está ligada a la branch development
en el repositorio remoto, y si hemos avanzado con el desarrollo en uno o más commits, podemos ejecutar el comando:
1git push origin development
Esto subirá los cambios que hayamos realizado en local hacia el repositorio remoto, en esa branch. Como mencionamos antes, solo se pueden subir cambios que estén guardados en un commit.
Por otro lado, si estamos creando una nueva branch local que queremos que esté ligada a una branch remota, debemos ejecutar el comando con la opción -u
o --set-upstream
. Por ejemplo:
1git push -u new-feature origin new-feature
Esto hará que la branch local quede ligada con la branch remota y posteriormente solo tengamos que ejecutar git push
para subir los cambios a la branch correspondiente.
Además hará que cuando traigamos los cambios del repositorio remoto, estos se comparen automáticamente con la branch correspondiente.
git fetch
Descarga y actualiza la información de los cambios del repositorio remoto (de todas las branches, si la branch actual no está ligada a una remota).
Esto no actualiza las branches locales automáticamente, solo descarga los cambios para que podamos compararlos y ver las diferencias. Si deseamos incorporar cambios de una branch del repositorio remoto podremos hacerlo con un comando independiente (git pull
).
Si se crearon nuevas branches en el repositorio remoto, también descargará la información de estas. Pero no las creará en local, esto debe hacerse manualmente (cuando corresponda o sea necesario).
También es posible indicar exactamente qué remote y qué branch se deasea descargar indicándola como argumento, por ejemplo:
1git fetch origin development
Esto descargará solo los cambios (si los hay) de la branch development
.
git diff
Cuando existen cambios en el repositorio, git diff
nos muestra qué archivo cambió y exactamente en qué línea, indicando si se agregó o borró algo.
En este caso solo teníamos un archivo (main.py
) y hemos agregado una línea. Así que solo nos mostrará los cambios de ese archivo.
Git nos muestra, en color rojo, las lineas modificadas, en este caso solo la primera, y en verde las nuevas líneas.
A simple vista, pareciera que la primera línea no se modificó, pero el cambio que detecta Git es el carácter de salto de línea (el cual no se muestra normalmente).
Al ejecutar simplemente git diff
la salida puede ser extensa, si tenemos muchos archivos con modificaciones. En estos casos podemos ver únicamente los cambios de un archivo indicando su nombre como argumento. Por ejemplo:
1git diff database.py
Si la salida de git diff
es muy extensa, se mostrará por partes en la pantalla, y deberemos desplazarnos con las teclas direccionales o de avance de página.
En estos casos Git se mantendrá en esta salida hasta que salgamos forzosamente con la tecla q
.
git merge <branch>
Este comando sirve para fusionar los cambios de la branch indicada como argumento (<branch>
) con la branch actual (desde la cual se ejecuta el comando).
Por ejemplo, si tenemos las branches main
y new-feature
, realizamos cambios (commits) en new-feature
y queremos llevar esos cambios a la branch main
, debemos ejecutar los siguientes comandos:
1git checkout main # si es que no estamos ya en esta branch2
3git merge new-feature
Idealmente ambas branches no deben tener cambios sin guardar. O sea, sus archivos deberían estar en un estado committed.
Siempre y cuando no hayan cambios simultáneos en ambas branches, en los mismos archivos, Git podrá fusionar las branches automáticamente.
En caso contrario, si, por ejemplo, hay cambios en las dos branches en un mismo archivo, en una misma línea, se dará lo que se conoce como conflicto de merge.
Esto quiere decir que Git no pudo fusionar las branches automáticamente, ya que no puede decidir con cuál cambio quedarse. La fusión se suspenderá hasta que se resuelva el conflicto (en Git bash se mostrará la leyenda (branch|MERGING)
en el prompt).
La resolución del conflicto recaerá sobre el desarrollador, quien deberá decidir con qué cambios quedarse y realizar un nuevo commit que resuelva el conflicto.
Más adelante, veremos con más profundidad cómo resolver conflictos de merge. Mientras tanto, si no podemos o no sabemos cómo resolver un conflicto de merge, podemos abortar el merge usando la opción --abort
.
1git merge --abort
git pull <remote> <branch>
Sirve para descargar y fusionar cambios desde una branch de un repositorio remoto a una branch local. Es decir, realiza primero un fetch de la branch indicada y luego un merge de esa branch sobre la branch actual.
1git pull origin development
Como en cualquier merge, es posible que ocurran uno o más conflictos.
git help <comando>
Si queremos obtener ayuda (documentación oficial) sobre algún comando, podemos usar el comando help
seguido del comando de interés:
1git help <comando>
Esto lanzará automáticamente el navegador web por defecto del sistema y mostrará la página del manual del comando indicado como argumento.
Probá tus conocimientos
¿Cuál es la diferencia entre git pull
y git fetch
?
¿Qué comando debemos utilizar para ver una lista de las branches de un repositorio?