Saltar a contenido

Resumen de comandos Git

Comandos principales para trabajar con Git de forma individual. Los comandos relacionados con el trabajo en equipo los veremos en la práctica 2.

Al final del documento se incluyen enlaces a apartados del libro Pro Git. Es un libro totalmente recomendable, deberías bajártelo y guardarlo como material de aprendizaje y de referencia. Está disponible de forma gratuita en múltiples versiones (PDF, eBook, HTML y mobi).

1. Comandos básicos

  • Configurar el usuario y dirección de correo en git:

    $ git config --global user.name "John Doe"
    $ git config --global user.email johndoe@example.com
    
  • Inicializar git en un directorio:

    $ cd /ruta/a/mi/directorio
    $ git config --global user.name <nombre-usuario>
    $ git config --global user.email <email>
    $ git init
    $ git add .
    $ git commit -m "Versión inicial"
    
  • Publicar por primera vez el repositorio local en el remoto (en GitHub):

    $ git remote add origin <url-repo>.git
    $ git push -u origin main
    

    El nombre del repositorio remoto será origin (nombre estándar del repositorio remoto en el caso en el que sólo haya uno). Subimos al repositorio la rama main (la rama por defecto que se crea al inicializar el repositorio local).

  • Comprobar el estado del repositorio local:

    $ git status
    
  • Comprobar las diferencias entre los ficheros modificados en el directorio de trabajo y el último commit:

    $ git diff
    
  • Añadir un fichero al stage (añadirlo para el próximo commit):

    $ git add <fichero o directorio>
    

    El área de stage también se llama el index. Es muy importante entender su funcionamiento para trabajar con Git. El siguiente dibujo muestra su funcionamiento:

  • Hacer un commit de los ficheros en el stage:

    $ git commit -m "Mensaje"
    
  • Eliminar un fichero del stage (si lo hemos añadido, pero al final decidimos no añadirlo en el siguiente commit):

    $ git reset HEAD <fichero>
    
  • Se puede combinar en un único comando el add y el commit en ficheros ya añadidos al control de versiones:

    $ git commit -a -m "Mensaje"
    

    Se puede abreviar como

    $ git commit -am "Mensaje"`
    
  • Deshacer un commit (sin perder los cambios que se han introducido en él):

    $ git reset HEAD^
    

    Los ficheros modificados seguirán estando en el directorio, con las modificaciones incluidas, pero fuera del área de stage. Para hacer un nuevo commit hay que volver a añadirlos haciendo add.

  • Eliminar todos los cambios realizados en el directorio, volviendo al último commit (¡Peligroso: perdemos todos los cambios del último commit!)

    $ git reset --hard HEAD
    $ git clean -fd (si se ha añadido algún fichero)
    
  • Publicar los cambios en el repositorio remoto:

    $ git push
    
  • Si hay commits en el repositorio remoto que queremos eliminar y cambiarlos por los commits en el directorio local:

    $ git push --force
    
  • Consultar los mensajes de los commits (toda la historia de la rama actual). La opción --oneline muestra sólo la primera línea del mensaje, la opción --graph muestra el grafo de dependencias y la opción --allmuestra el grafo completo, no sólo aquel en el que estamos (HEAD).

    $ git log [--oneline] [--graph] [--all]
    
  • Comprobar las diferencias entre dos commits:

    $ git diff <hash-previo> <hash-nuevo>
    

    Devuelve las cambios que se han introducido desde el commit identificado por y hasta el .

2. Ramas

Es muy importante entender que las ramas en Git son como etiquetas móviles. La rama en la que estamos se actualiza de posición cada vez que hacemos un nuevo commit. Git mantiene en la referencia HEAD la rama actual.

  • Crear una rama nueva:

    $ git checkout -b nueva-rama
    M   hola.txt (si hay cambios en el espacio de trabajo se llevan a la nueva rama)
    Switched to a new branch 'nueva-rama'
    
  • Listar todas las ramas de un repositorio (incluyendo ramas remotas)

    $ git branch -av
    main
    * nueva-rama
    $ git commit -a -m "Confirmamos los cambios en la nueva rama"
    
  • Moverse a otra rama:

    $ git checkout main
    Switched to branch 'main'
    
  • Mostrar un fichero de una rama (o commit) dado:

    $ git show <commit o rama>:<nombre-fichero>
    
  • Comparar dos ramas:

    $ git diff main nueva-rama
    

    El comando git diff main nueva-rama devuelve las diferencias entre las ramas main y nueva-rama: las modificaciones que resultarían de mezclar la rama nueva-rama en la rama main.

  • Merge de ramas: Mezclar la rama nueva-rama en la rama main (añade a la main los commits adicionales de la rama nueva-rama):

    $ git checkout main
    $ git merge [--no-ff] nueva-rama -m "Mensaje de commit"
    

    La opción --no-ff no hace un fast forward y mantiene separados los commits de la rama en el log de commits. Es útil para revisar la historia del repositorio.

  • Si en la rama que se mezcla y en la actual hay cambios que afectan a las mismas líneas de un fichero, git detecta un conflicto y combina esas líneas conservando las dos versiones y añadiendo la información de la procedencia. Debemos resolver el conflicto: editarlos a mano y volver a hacer add y commit.

    $ git merge nueva-rama
    CONFLICT (content): Merge conflict in hola.txt  
    Automatic merge failed; fix conflicts and then commit the result.  
    # editar a mano el fichero con conflictos
    $ git commit -a -m "Arreglado el conflicto en el merge"
    $ git merge nueva-rama
    

    El comando git status después de un merge nos indica qué ficheros no se han mezclado y hay que editar manualmente.

  • Rebase de una rama. Si la rama main ha avanzado después de separar una rama alternativa y queremos incorporar esos cambios en la rama alternativa podemos hacer un git rebase:

    $ git checkout -b experiment
    # hacemos cambios
    $ git commit -m "Cambios en experiment"
    $ git checkout main  
    # hacemos cambios  
    $ git commit -a -m "Cambios en main"  
    $ git checkout experiment
    $ git rebase main  
    First, rewinding head to replay your work on top of it...  
    Applying: Corregido bug1  
    Applying: Corregido bug2
    

    El comando cambia la historia de la rama: primero la mueve al final de la rama main (rewind head) y a partir de ahí aplica los cambios propios de la rama.

    ¡Cuidado!

    No se debe hacer un rebase de commits que existan en otros repositorios locales de compañeros. Al volver a aplicar los commits sobre los commits rebobinados, se cambia su número de hash (identificador) y se convierten en commits distintos.

    Una vez que hemos hecho el rebase ya podemos añadir mover la rama main y tener una historia lineal:

    $ git checkout main
    $ git merge nueva-rama
    # Borramos la rama una vez mezclada
    $ git branch -d nueva-rama
    
  • Igual que en el merge, al hacer un rebase pueden aparecer conflictos al hacer el rebase, basta con modificar los ficheros con conflictos, añadirlos y continuar el rebase:

    $ git rebase main
    CONFLICT (content): Merge conflict in <some-file>
    # hacemos git status para comprobar donde están los conflictos
    $ git status
    # Unmerged paths:
    # (use "git reset HEAD <some-file>..." to unstage)
    # (use "git add/rm <some-file>..." as appropriate to mark resolution)
    #
    # Editamos los ficheros para corregir los conflictos
    $ git add <some-file>
    $ git rebase --continue
    

    Nota

    Es posible integrar los cambios de una rama haciendo un merge o haciendo un rebase. Ambas estrategias son correctas y cada una tiene sus pros y contras. Nosotros vamos a usar ambas para aprender su funcionamiento.

  • Log en forma de grafo:

    $ git log --graph --oneline 
    
  • Borrar una rama:

    $ git branch -d nueva-rama  
    Deleted branch nueva-rama (was c241d7b)
    

    Sólo podemos borrar de la forma anterior ramas en las que no estamos y que se han mezclado con alguna otra. El comando anterior no permite borrar ramas activas que tienen commits sin mezclar con otras.

  • Borrar una rama descartando sus commits:

    $ git branch -D rama
    
  • Subir una rama al repositorio remoto:

    $ git push -u origin <rama>
    
  • Descargar una rama del repositorio remoto (origin, por ejemplo, el repositorio remoto por defecto)

    $ git fetch 
    $ git checkout -b <rama> origin/<rama>
    
  • Consultar ramas locales y conexiones repositorio remoto (origin, por ejemplo)

    $ git remote show origin
    
  • Subir todas las ramas y etiquetas:

    $ git push -u -all origin
    

    Al poner la opción -u hacemos tracking del repositorio remoto y las referencias quedan almacenadas en el fichero de configuración .git/config. A partir de ahora sólo es necesario hacer git push para subir los cambios en cualquiera de las ramas presentes.

  • Borrar una rama en repositorio remoto:

    $ git push origin --delete <branchName>
    

3. Modificar la historia

  • Modificar el mensaje del último commit. Se abrirá un editor en el que modificar el mensaje. También se puede escribir el mensaje a mano:

    $ git commit --amend [--m "Nuevo mensaje"]
    
  • Deshacer el último commit (sólo la acción del commit, dejando los cambios en el stage):

    $ git reset --soft HEAD^
    
  • Descartar el último merge y volver a la situación anterior al hacer el merge:

    $ git reset --merge ORIG_HEAD
    
  • Movernos atrás a un commit pasado, mirar los ficheros, crear una nueva rama allí (o no) y volver al commit actual:

    $ git checkout <hash> (o tag, por ejemplo v2.0)
    You are in 'detached HEAD' state.
    # Ahora estás en un detached HEAD
    $ git branch
    * (HEAD detached at 594b606)
    main
    $ git checkout -b v2.0.1
    Switched to a new branch 'v2.0.1'
    $ git branch
    main
    * v2.0.1
    $ git checkout main
    
  • Movernos atrás a un commit pasado, descartando todos los commits realizados después (peligroso)

    $ git reset --hard <hash>
    

4. Más información

Puedes encontrar más información en los siguientes documentos: