Inicio
Artículos
Categorias
Etiquetas
Uso básico de Git con GitLab y GitHub
publicado el: 2022-2-23   actualizado el: 2022-2-23   incluido en: Sistema Control de Versiones , Linux
palabras totales: 6267   tiempo de lectura: 30 mins  

Github y GitLab son servicios web que permiten alojar el código de proyectos utilizando el software de control de versiones Git.

Ambos servicios tienen cuentas gratuitas y de pago. La cuenta gratuita de ambas permite crear repositorios públicos y privados desde 2019, año en que Github cambió su política y permitió los repositorios privados en la cuenta gratuita.

Creación de cuentas en GitHub/GitLab

Este es un paso sencillo, basta con entrar en la web de GitHub o en la de GitLab y seguir el proceso para registrarse que desde ella me ofrece. Como quiero asociar mis cuentas con Git, lo mas cómodo es que el nombre del usuario y el correo electrónico sean el mismo en cada cuenta.

Asociación de Git con las cuentas de GitHub/GitLab

Antes que nada, necesito comprobar si tengo instalado Git en mi sistema, porque sino tendría que instalarlo.

Git, es un software de control de versiones diseñado por Linus Torvalds. Su propósito es llevar registro de los cambios en archivos de computadora incluyendo coordinar el trabajo que varias personas realizan sobre archivos compartidos en un repositorio de código.

Para comprobar si está instalado en el sistema escribo en la terminal:

1
2
usuario@mi-pc:~ $ git --version
git version 2.30.2

En mi caso si está instalado. Para instalar Git en una distribución GNU/Linux basada en Debian o Ubuntu bastaría con escribir lo siguiente en el terminal:

1
usuario@mi-pc:~ $ sudo apt install git

Configuración de Git

Una vez que estoy seguro de tener instalado git es hora de empezar a configurarlo. Desde el terminal tecleo lo siguiente:

1
2
usuario@mi-pc:~ $ git config --global user.name "Mi usuario aquí"
usuario@mi-pc:~ $ git config --global user.email "usuario@email.com"

El email tiene que ser el mismo que el de la cuenta de GitHub o GitLab

Configurada globalmente mi identidad puedo elegir el editor de texto por defecto que se utilizará cuando Git necesite que introduzca un mensaje. Si no indico nada, Git usará el editor por defecto de mi sistema, en este caso es nano.

1
2
3
$ git config --global core.editor "nano -w"
# O también elegir vs code
$ git config --global core.editor "code --wait"

Generar SSH KEY

Para poder conectarme via ssh debo crear una ssh key. Esta llave se va a utilizar para establecer una conexión segura entre Github o GitLab y mi ordenador. Parto de la base que no tengo ninguna llave generada. Para comprobarlo escribo lo siguiente en el terminal:

1
2
3
4
usuario@mi-pc:~$ cd ~/.ssh
usuario@mi-pc:~/.ssh $ ls
config  known_hosts
usuario@mi-pc:~/.ssh $ 

Si tuviera alguna llave generada tendría que aparecer alguno de estos dos archivos.

1
2
id_rsa
id_dsa.pub

En el caso de tenerlo ignoraría el siguiente paso y pasaría directamente instalar xclip.

Generación de la clave

Para generarla llave tecleo lo siguiente en el terminal:

1
usuario@mi-pc:~ $ ssh-keygen -t rsa -C "usuario@email.com"

Aparece lo siguiente:

1
Generating public/private rsa key pair. # Enter file in which to save the key (/home/you/.ssh/id_rsa):

Le doy al enter sin escribir nada y entonces me pide que escriba dos veces una contraseña. Esta contraseña me la va a pedir cada vez que quiera subir algo a mi cuenta. Me aparece esto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
usuario@mi-pc:~/.ssh $ ssh-keygen -t rsa -C "usuario@email.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/Usuario/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/Usuario/.ssh/id_rsa
Your public key has been saved in /home/Usuario/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:oEJknc0DLPMBHsclNK7OQ932mrWX8H2eSY/0o2mbzEg usuario@email.com
The key's randomart image is:
+---[RSA 3072]----+
|  =***.          |
| +o+*o+          |
|  o+...          |
| . o.o .         |
|  + o o S        |
| + . . .         |
|  +      o E  o  |
|   .   + .= =++B |
|      o .. ..XB +|
+----[SHA256]-----+
usuario@mi-pc:~/.ssh $ 

Ahora la llave creada debería estar en:

1
~/.ssh/id_rsa.pub

Puedo copiarla manualmente o usando el programa xclip desde la linea de comandos.

Instalación de xclip

1
usuario@mi-pc:~/.ssh $ sudo apt install xclip

Instalo el programa xclip. Va a pedir la contraseña de Linux (no confundir con la contraseña de Git)

Una vez instalado escribo lo siguiente para copiar la llave:

1
usuario@mi-pc:~/.ssh $ xclip -sel clip < ~/.ssh/id_rsa.pub

Añadir una llave SSH a GitHub o GitLab

Para ello entro en mis cuenta de Github y GitLab y arriba a la derecha pulso sobre mi foto de usuario, voy a «Settings» y finalmente a «SSH Keys». En el caso de GitHub tengo que presionar también en «Add SSH Key»

En «title» puedo poner lo que me apetezca o dejarlo en blanco (va a aparecer mi correo). En la parte de «Key» pego lo que anteriormente copie con el programa xclip (simplemente botón derecho-pegar o ctrl + v). Finalmente le doy a «Add Key»

Funcionamiento

Para comprobar que lo tengo enlazado correctamente escribo lo siguiente:

Nota: aparece una ventana pidiendo una contraseña, debo introducir la contraseña puesta en la configuración de la SSH Key. Si no lo hago saldrá «Permission denied (publickey)»

Para GitHub:

1
2
3
4
5
6
7
8
usuario@mi-pc:~/.ssh $ ssh -T git@github.com
The authenticity of host 'github.com (140.82.121.4)' can't be established.
ECDSA key fingerprint is SHA256:p2QAJJNICHGJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com,140.82.121.4' (ECDSA) to the list of known hosts.
Enter passphrase for key '/home/Usuario/.ssh/id_rsa': 
Hi usuario! You've successfully authenticated, but GitHub does not provide shell access.
usuario@mi-pc:~/.ssh $ 

Para GitLab:

1
2
3
4
5
6
7
8
usuario@mi-pc:~/.ssh $ ssh -T git@gitlab.com
The authenticity of host 'gitlab.com (172.65.251.78)' can't be established.
ECDSA key fingerprint is SHA256:Hbw3g8zVjNSksFbiTiUWPWg2Bq1x8xdGUrliXFzSnUw.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'gitlab.com,172.65.251.78' (ECDSA) to the list of known hosts.
Enter passphrase for key '/home/Usuario/.ssh/id_rsa': 
Welcome to GitLab, @usuario!
usuario@mi-pc:~/.ssh $ 

Si aparece el mensaje «Permission denied (publickey)» en más ocasiones Github tiene una página dedicada a solucionar este problema: https://help.github.com/articles/error-permission-denied-publickey

Empezar a usar GitHub/GitLab

Para subir mi código a GitHub o GitLab puedo subir el código de un repositorio local de mi ordenador, o hacer un fork de otro repositorio remoto.

Nota: un repositorio es básicamente un lugar/espacio centralizado donde se almacena, organiza, mantiene y difunde información digital, habitualmente archivos informáticos. Pueden ser locales o estar en una red informática (por ejemplo internet).

Subir un proyecto almacenado en el ordenador personal.

Primero necesito crear un nuevo repositorio remoto en Github y/o Gitlab donde almacenar el código.

Crear un repositorio remoto

GitHub

Una vez entro en mi cuenta, en la pestaña de repositorios me aparecerá un botón verde con el nombre de «new repository» que me permitirá crear un nuevo proyecto.

Una vez creado, se sitúa en el automáticamente y muestra una pantalla con instrucciones para iniciar a trabajar con el repositorio remoto y poder vincularlo a otro que tengamos o creemos en local. Nos da dos opciones, vía https o vía ssh.

ssh

https

GitLab

Dentro en mi cuenta de GitLab, hay una sección para crear un proyecto. Donde va a aparecer una página en la que puedo configurar un nuevo repositorio indicando su nombre, descripción, licencia y si será privado o público.

Una vez creado, muestra una pantalla con instrucciones para iniciar a trabajar con el repositorio remoto y poder vincularlo a otro que tengamos o creemos en local.

Creando un repositorio local

Me sitúo en la carpeta donde quiero crear el repositorio local y lo creo desde la línea de comandos

1
2
usuario@mi-pc:~ $ mkdir proyecto_local_gh
usuario@mi-pc:~ $ cd proyecto_local_gh/

Entro de la carpeta del que será el repositorio local creo un archivo markdown como primer contenido del mismo.

1
usuario@mi-pc:~ $ echo "# Primer proyecto en github" >> README.md

Transformo la carpeta en repositorio local creándose una carpeta oculta llamada .git.

1
2
usuario@mi-pc:~ $ git init
Inicializado repositorio Git vacío en /home/Enrique/repositorios_github/Pruebas/proyecto_local_gh/.git/

Para comprobar lo que se ha añadido al staging area para subir escribo:

1
usuario@mi-pc:~ $ git status

Los archivos que aparecen en verde ya están añadidos, y los archivos en rojo son los que faltan por añadir.

Ya puedo hacer un commit para confirmar los cambios y enviar los archivos de la zona de Index al repositorio local. Lo que sale entre comillas es el comentario que va a parecer en el commit.

1
2
3
4
usuario@mi-pc:~ $ git commit -m "primer commit"
[mainlab (commit-raíz) 53bdb81] primer commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

Como se puede observar el nombre de la rama del mi repositorio local es mainlab porque he configurado git para que así sea con el comando siguiente

1
usuario@mi-pc:~ $ git config --global init.defaultbranch mainlab

Sino por defecto el nombre sería master.

Cambio el nombre de la rama local y lo dejo como quiero que se llame en el repositorio remoto de Github.

1
usuario@mi-pc:~ $ git branch -M maingh

Configurando repositorios remotos

Lo siguiente es asignar el repositorio remoto al que quiero subir el proyecto local. Los repositorios remotos son proyectos alojados en servidores, como Github/Gitlab. git remote me permite usar un nombre corto (alias) para ejecutar comandos en lugar de escribir una URL remota completa. Yo en el ejemplo he optado hacerlo a través de ssh:

Github

1
2
3
4
5
6
7
8
9
# Modelo mediante ssh
usuario@mi-pc:~ $ git remote add origin git@github.com:nombre_de_usuario/nombre_del_repositorio.git
# ejemplo
usuario@mi-pc:~ $ git remote add origin_gh git@github.com:esaborit/proyecto_github.git

# Modelo mediante https
usuario@mi-pc:~ $ git remote add origin https://github.com/nombre_de_usuario/nombre_del_repositorio.git
# ejemplo
usuario@mi-pc:~ $ git remote add origin https://github.com/esaborit/proyecto_github.git

Nota: git@github.com:nombre_de_usuario/nombre_del_repositorio.git, es una de las diferentes formas de especificar el acceso a un repositorio a través de SSH; esta es la “sintaxis de estilo scp” descrita en la documentación. Que el nombre de usuario en la sintaxis de estilo scp es git se debe a la forma en que GitHub trata con la identificación de usuarios: esencialmente, ese nombre de usuario se ignora y el usuario se identifica en función del SSH key-par que solían autenticar.

origin, oring_gh y oring_gl son los nombres de las referencias de los repositorios remotos, que sirven de atajo para llamar a las url de los repositorios remotos, puedo usar cualquiera de los nombres en la línea de comandos en lugar de la URL entera

Gitlab

1
2
3
4
5
6
7
# Modelo mediante ssh
usuario@mi-pc:~ $ git remote add origin_gl git@gitlab.com:nombre_de_usuario/nombre_del_repositorio.git
# ejemplo
usuario@mi-pc:~ $ git remote add origin_gl git@gitlab.com:esaborit/proyecto_gitlab.git

# Modelo mediante https
usuario@mi-pc:~ $ git remote add origin_gl https://gitlab.com/nombre_de_usuario/nombre_del_repositorio.git

Cargando el contenido del repositorio local a un repositorio remoto

Finalmente escribo la orden para subirlo todo a mi GitHub dentro del repositorio que he creado anteriormente.

1
2
3
4
5
6
7
8
9
usuario@mi-pc:~ $ git push -u origin_gh maingh
Enter passphrase for key '/home/Enrique/.ssh/id_rsa': 
Enumerando objetos: 3, listo.
Contando objetos: 100% (3/3), listo.
Escribiendo objetos: 100% (3/3), 234 bytes | 234.00 KiB/s, listo.
Total 3 (delta 0), reusado 0 (delta 0), pack-reusado 0
To github.com:esaborit/proyecto_github.git
 * [new branch]      maingh -> maingh
Rama 'maingh' configurada para hacer seguimiento a la rama remota 'maingh' de 'origin_gh'.

El código de la rama local maingh se va a subir en la rama remota maingh, que si no existe se creará automáticamente con la ejecución del comando anterior.

La -u equivale a --set-upstream y se refiere al repositorio remoto principal al que haré pull y push, esta opción solo es necesario utilizarla una sola vez.

Cuando se tiene mas de un repositorio remoto se puede utilizar esta opción para configurar uno de ellos como el principal… suponiendo que tengo un repositorio en BitBucket (bitbucket), otro en GitHub (origin_gh) y otro en GitLab (origin_lab) y quisiera utilizar GitHub (origin_gh) como principal, tendría que hacer git push -u origin_gh <branch> y las siguientes veces al hacer solo git push lo hará a GitHub sin tener que especificar el repositorio pero para los otros dos si tendría que hacerlo, ej. git push bitbucket <branch> o git push origin_lab <branch>.

Si tienes un solo repositorio y quieres evitar estar escribiendo git push origin <branch> puedes utilizar esta opción y solo hacer git push las siguientes veces.

A esta opción también se le conoce como “argument-less git-pull/push (git-pull/push sin argumentos)”

Puedo ver como ha quedado configurada la rama remota maingh con el comando git remote show origin_gh:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
usuario@mi-pc:~ $ git remote show origin_gh 
Enter passphrase for key '/home/Enrique/.ssh/id_rsa': 
* remoto origin_gh
  URL  para obtener: git@github.com:esaborit/proyecto_github.git
  URL para publicar: git@github.com:esaborit/proyecto_github.git
  Rama HEAD: maingh
  Rama remota:
    maingh rastreada
  Rama local configurada para 'git pull':
    maingh fusiona con remoto maingh
  Referencia local configurada para 'git push':
    maingh publica a maingh (actualizado)

Ahora si entro en GitHub y selecciono mi repositorio, podré ver todos los cambios que se han producido.

Voy a añadir a mi repositorio local un segundo repositorio remoto, en este caso el creado en GitLab. Desde la consola me sitúo dentro de mi repositorio local y empiezo configurando el segundo repositorio remoto

1
usuario@mi-pc:~ $ git remote add origin_gl git@gitlab.com:esaborit/proyecto_gitlab.git

Escribo el comando push para subir la rama maingh del repositorio local al repositorio remoto en GitLab que acabo de crear y donde se almacenará en una rama del mismo nombre maingh.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ git push -u origin_gl maingh
    Enter passphrase for key '/home/Enrique/.ssh/id_rsa': 
    Enumerando objetos: 3, listo.
    Contando objetos: 100% (3/3), listo.
    Escribiendo objetos: 100% (3/3), 234 bytes | 234.00 KiB/s, listo.
    Total 3 (delta 0), reusado 0 (delta 0), pack-reusado 0
    To gitlab.com:esaborit/proyecto_gitlab.git
    
   * [new branch]      maingh -> maingh
     Rama 'maingh' configurada para hacer seguimiento a la rama remota 'maingh' de 'origin_gl'.

Ahora si entro en GitLab y selecciono mi repositorio, podré ver todos los cambios que se han producido.

Compruebo la configuración de las ramas remotas

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Ramas en github
$ git remote show origin_gh 
Warning: Permanently added the ECDSA host key for IP address '140.82.121.3' to the list of known hosts.
Enter passphrase for key '/home/Enrique/.ssh/id_rsa': 
* remoto origin_gh
  URL  para obtener: git@github.com:esaborit/proyecto_github.git
  URL para publicar: git@github.com:esaborit/proyecto_github.git
  Rama HEAD: maingh
  Rama remota:
    maingh rastreada
  Referencia local configurada para 'git push':
    maingh publica a maingh (actualizado)

# Ramas en gitlab
$ git remote show origin_gl
Enter passphrase for key '/home/Enrique/.ssh/id_rsa': 
* remoto origin_gl
  URL  para obtener: git@gitlab.com:esaborit/proyecto_gitlab.git
  URL para publicar: git@gitlab.com:esaborit/proyecto_gitlab.git
  Rama HEAD: maingh
  Rama remota:
    maingh rastreada
  Rama local configurada para 'git pull':
    maingh fusiona con remoto maingh
  Referencia local configurada para 'git push':
    maingh publica a maingh (actualizado)

Clonar un repositorio Git

Cuando encuentro un repositorio que me resulta de utilidad y quiero trabajar con el en local puedo proceder de dos formas, lo puedo descargar en formato zip o lo puedo clonar. La clonación presenta algunas ventajas frente a la descarga en formato zip.

  • Crea un repositorio Git en local con los cambios que el repositorio remoto ha tenido a lo largo del tiempo.
  • Podré luego enviar cambios al repositorio remoto, una vez los haya realizado en local.

Para clonar un repositorio

Primero copiar la URL del repositorio remoto que deseo clonar (ver el icono “Copy to clipboard” en la siguiente imagen).

Luego abro una ventana del terminal, para situarme sobre la carpeta del proyecto que quiero clonar. Es recomendable crear ya directamente una carpeta con el nombre del proyecto a clonar, o cualquier otro nombre que te parezca mejor para este repositorio. Me sitúo dentro de esa carpeta y desde ella lanzo el comando para hacer el clón, que sería algo como esto:

1
usuario@mi-pc:~ $ git clone https://github.com/esaborit/prueba.git

El último punto me indica que el clon lo va a colocar en la carpeta donde estoy situado. La salida de ese comando sería más o menos así:

1
2
3
4
5
6
7
8
usuario@mi-pc:~/repositorios_github/Pruebas $ git clone https://github.com/esaborit/prueba.git
Clonando en 'prueba'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 3 (delta 0), pack-reused 0
Recibiendo objetos: 100% (6/6), listo.
usuario@mi-pc:~/repositorios_github/Pruebas $ 

Clonando para gitlab

1
2
3
4
# Desde ssh
usuario@mi-pc:~ $ git clone git@gitlab.com:esaborit/prueba.git
# Desde https
usuario@mi-pc:~ $ git clone https://gitlab.com/esaborit/prueba.git

Instalar las dependencias

Habitualmente los desarrollos de Git tienen ignoradas las dependencias mediante el archivo .gitignore, por ello es importante que las instalemos de nuevo en el repositorio clon, en local.

Para cada tipo de proyecto, con cada lenguaje, existirán comandos para instalar las dependencias. Este comando lo tendría que conocer con anterioridad para poder aplicarlo, si es de PHP dependerá de Composer, si es de NodeJS (o Javascript) dependerá de npm.

Subir cambios, realizados por mi, al repositorio remoto clonado

Una vez modificado el código en local, puedo subir los cambios al repositorio remoto. Al clonar el repositorio en local, está asociado el origen remoto desde donde lo traje. Sin embargo, hay que tener en cuenta:

  • Las normas del propietario del repositorio para enviar cambios, como por ejemplo trabajar siempre con ramas y enviar los cambios a una rama en concreto, que luego se puede fusionar con un pull request.
  • Si no tengo permisos por no ser mío el repositorio remoto, no puedo enviar cambios y debería haber hecho un Fork.

Suponiendo que el repositorio es mío y que puedo enviar cambios directamente a la rama main, para enviar cambios a GitHub o cualquier otro hosting de repositorios, haría:

1
usuario@mi-pc:~ $ git push

Con eso se envían los cambios al instante y los podré ver reflejados en el repo remoto.

Nota: para que se envíen los cambios del repositorio, local tienen que haber sido realizadas alguna/s modificación/es en el código del proyecto y confirmado con el correspondiente/s commit.

Hacer un fork de otro proyecto

Si el repositorio que voy a modificar no es mío y pretendo continuar el desarrollo, agregando cambios que querré enviar a GitHub/GitLab, tendré < que clonar el repositorio de otra manera.

Primero debo crear un “fork”. Esto es, un repositorio que es copia de otro que ya está publicado en GitHub. Lo bueno de un fork es que el repositorio será exactamente igual, pero estará en mi cuenta de GitHub, con mi usuario, por lo que tendré permisos para hacer lo que yo quiera con él.

Hacer un fork de otro repositorio significa que lo copio hacia mi repositorio remoto en GitHub o GitLab. Esto significa que guarda los commits que se hayan hecho y sus ramas.

Hacer un fork es muy fácil, busco un repositorio que me interese, entro en el y selecciono «Fork» para copiarlo a mi cuenta.

Hay un botón para hacer el fork en la parte de arriba de la página del repositorio.

img

Una vez hecho el fork, el repositorio ya me pertenece. Puedo clonar (el fork, no el repositorio original) y realizar los cambios que quiera y podré subirlos perfectamente a mi propio repositorio (mi fork).

El resto del proceso, para descargar el repositorio, modificarlo y enviar los cambios es exactamente igual que lo descrito anteriormente, incluido el git push para enviar los cambios.

Crear nuevas ramas

Esta opción la realizaré desde dentro de mi repositorio remoto. Selecciono «branch: main» y se abrirá una lista, y un lugar para escribir. Allí escribo el nombre de la rama que quiero usar, como no la encontrará me dirá que debo crear una nueva.

Si en vez de en el repositorio remoto de Github o GitLab quiero crear una nueva rama en el repositorio local de mi ordenador puedo utilizar el comando

1
usuario@mi-pc:~ $ git branch nombre_de_la_rama_nueva

Comandos para seleccionar la rama

Un poco más atrás he creado una nueva rama ahora debo seleccionarla para trabajar en ella.

Para ver que ramas tengo debo escribir lo siguiente en el terminal:

1
usuario@mi-pc:~ $ git show-branch

Para moverme entre ramas uso el comando git checkout seguido del nombre de la rama que quiero que sea la activa. Para seleccionar la rama deseada escribo lo siguiente:

1
usuario@mi-pc:~ $ git checkout nombre_de_la_rama_nueva

Esta sencilla operación tiene mucha potencia, porque cambiará automáticamente todos los archivos del proyecto, los de todas las carpetas, para que tengan el contenido en el que se encuentren en la correspondiente rama.

De momento en el ejemplo las dos ramas tenían exactamente el mismo contenido, pero ahora podría empezar a hacer cambios en la rama nueva y sus correspondientes commit y entonces los archivos tendrán códigos diferentes, de modo que se pueda ver que al pasar de una rama a otra hay cambios en los archivos.

Si estando en la rama nueva hago un par de commit, puedo observar que al hacer el show-branches muestra nuevos datos.

Cuando quiero crear la rama local en un repositorio remoto (agregar una rama remota) y vincularlas, la primera vez, debo usar la opción -u / --set-upstream . Garantiza que se construye una relación de seguimiento entre la rama local y la remota que he creado. A partir de ahora Git sabrá lo que quiero hacer cuando uso los comandos git fetch, git pull o git push en el futuro. Mantiene las ramas locales y remotas actualizadas con el seguimiento y mantenimiento de los comandos pull y push.

1
2
3
4
usuario@mi-pc:~ $ git push --set-upstream <remote> <branch>
usuario@mi-pc:~ $ git push -u <remote> <branch>
# Por ejemplo
usuario@mi-pc:~ $ git push --set-upstream origin experimental

Ahora cada vez que haga

1
usuario@mi-pc:~ $ git push

se subirá dentro de la rama seleccionada dejando las demás tal como estaban.

El comando checkout tiene la posibilidad de permitirme crear una rama nueva y moverme a ella en un único paso. Para crear una nueva rama y situarme sobre ella tendré que darle un nombre y usar el parámetro -b.

1
usuario@mi-pc:~ $ git checkout -b otra_rama

Fusionar ramas

A medida que cree ramas y cambie el estado del las carpetas o archivos, en el proyecto empezarán a divergir una rama de la otra. Llegará el momento en el que interese fusionar ramas para poder incorporar el trabajo realizado a la rama main (antes master).

El proceso de fusionado se conoce como "merge" y puede llegar a ser muy simple o más complejo si se encuentran cambios que Git no pueda procesar de manera automática. Git para procesar los merge usa un antecesor común y comprueba los cambios que se han introducido al proyecto desde entonces, combinando el código de ambas ramas.

Para hacer un merge me sitúo en una rama, en este caso la main, y decido con qué otra rama se debe fusionar el código.

El siguiente comando, lanzado desde la rama main, permite fusionarla con la rama experimental.

1
usuario@mi-pc:~ $ git merge experimental

Un merge necesita un mensaje, igual que ocurre con los commit, por lo que al realizar ese comando, en mi caso, se abrirá el editor nano (o cualquier otro editor de consola que esté configurado) para poder introducir los comentarios oportunos. Esta operativa de indicar el mensaje se puede resumir con el comando -m:

1
usuario@mi-pc:~ $ git merge experimental -m 'Esto es un merge con mensaje'

En resumen una secuencia de comandos podría ser: Primero el cambio a la rama main git checkout main, luego el git branch para confirmar en qué rama nos encontramos y por último el merge para fusionarla con la rama experimental.

Luego puedo comprobar que la rama main tiene todo el código nuevo de la rama experimental y podré hacer nuevos commits en main para seguir el desarrollo del proyecto ya con la rama principal.

Fusionar los cambios de master en la rama en desarrollo

Durante tu trabajo en el desarrollo del proyecto gestionado con Git también puede ser normal que se vayan haciendo cambios en la rama main, o en otras ramas en desarrollo, y quieras traerlos para tu rama actual. Por ejemplo, la rama experimental está tardando varios días o semanas en completarse y mientras tanto han agregado nuevas features que quieras que esté disponibles también en la rama experimental.

Entonces seguramente querrás traerte los cambios de la rama master. Para ello, estando en la rama experimental, puedes lanzar el siguiente comando.

1
usuario@mi-pc:~ $ git merge main -m 'Un mensaje del merge de main en la rama experimental'

Ya lo tienes! ahora tu rama está actualizada con todos los cambios en main. Puedes seguir desarrollando tu rama experimental sabiendo que tienes el proyecto actualizado.

Subir una rama a un repositorio remoto

Para que las ramas que creo en mi repositorio local se publiquen en Github o Gitlsb, tengo que realizar específicamente la acción de subir la rama que deseo.

Debo utilizar el comando push, indicando la opción -u y el nombre de la rama que deseo subir. Por ejemplo de esta manera:

1
2
3
usuario@mi-pc:~ $ git push -u origin experimental
# o tambien
usuario@mi-pc:~ $ git push --set-upstream origin experimental

Así estoy haciendo un push, empujando hacia origin (que es el nombre que se suele dar a la URL del repositorio remoto), la rama con nombre “experimental”.

Nota: al subir el proyecto a Github podré ver también un diagrama de las ramas que he ido creando y fusionando a main, en la sección Graps / Network.

Borrar una rama

En ocasiones puede ser necesario eliminar una rama del repositorio, por ejemplo porque me haya equivocado en el nombre al crearla. Aquí la operativa puede ser diferente, dependiendo de si he subido ya esa rama a remoto o si todavía solamente está en local.

Borrado de la rama en local

Esto lo consigo con el comando git branch, solamente que ahora usando la opción -d para indicar que quiero borrarla.

1
usuario@mi-pc:~ $ git branch -d rama_a_borrar

Sin embargo, puede que esta acción no funcione porque haya hecho cambios que no se hayan salvado en el repositorio remoto, o no se hayan fusionado con otras ramas. En el caso que quiera forzar el borrado de la rama, para eliminarla independientemente de si se ha hecho el push o el merge, tendré que usar la opción -D.

1
usuario@mi-pc:~ $ git branch -D rama_a_borrar

Se debe prestar especial atención a esta opción -D, ya que al eliminar de este modo pueden haber cambios que ya no se puedan recuperar. Es bastante fácil de confundir con -d, opción más segura, ya que no permite borrado de ramas en situaciones donde se pueda perder código.

Eliminar una rama en remoto

Si la rama que quiero eliminar está en el repositorio remoto, la operativa es un poco diferente. Tengo que hacer un push, indicando la opción --delete, seguida de la rama que se desea borrar.

1
usuario@mi-pc:~ $ git push origin --delete rama_a_borrar

Descargar una rama de remoto

A veces ocurre que se generan ramas en remoto, por ejemplo cuando han sido creadas por otros usuarios y subidas a GitHub o similar, y necesito acceder a ellas en local para verificar los cambios o continuar el trabajo. En principio esas ramas en remoto creadas por otros usuarios no están disponibles para mi en local, pero las podré descargar.

El proceso para obtener una rama del repositorio remoto es bien sencillo. Lo consigo con el comando fetch.

1
usuario@mi-pc:~ $ git fetch

Lanzado ese comando he podido descargar la rama git de remoto. Ahora ya puedo acceder a ella.

1
usuario@mi-pc:~ $ git checkout mi_rama_remota_descargada

Otros comandos básicos

Además de los comandos anteriores, existen otros comandos muy usados que son interesantes conocer.

Operaciones con archivos

Mostraré la operativa en git con los archivos para: borrar, mover y renombrar archivos.

Eliminar archivos

La forma más fácil de borrar archivos del seguimiento y eventualmente del repositorio es git rm.

1
2
usuario@mi-pc:~ $ git rm tes2.txt
rm 'test2.txt'

Después de ejecutar este comando, el archivo test2.txt se elimina de la carpeta de trabajo y esta información de eliminación se ha añadido al área de preparación.

1
2
3
4
5
6
usuario@mi-pc:~ $ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	deleted:    test2.txt

Renombrar archivos

Si renombro el fichero en mi repositorio local directamente, git considera esta operación como dos operaciones, la primera es borrar los ficheros con el antiguo y el nuevo, y la segunda es añadir el fichero recién nombrado a la copia de trabajo.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
usuario@mi-pc:~ $ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	deleted:    test1.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	test1_rename.txt

no changes added to commit (use "git add" and/or "git commit -a")

El inconveniente de tal operación es que rompe el historial de revisiones del fichero, y no se podría obtener el historial de revisiones de este fichero recién nombrado antes de este momento de renombramiento. No es deseable en el control de versiones.

Git tiene un comando de renombrado para resolver este problema de enlazamiento roto - mv.

1
usuario@mi-pc:~ $ git mv test1.txt test1_rename.txt

mv significa en realidad mover, pero aquí, moverse de test1.txt a test1_rename.txt también significa renombrar el fichero.

Si compruebo el git status ahora, aparece renamed,

1
2
3
4
5
6
usuario@mi-pc:~ $ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	renamed:    test1.txt -> test1_rename.txt

Mover archivos

De manera similar a renombrar archivos, mover archivos en git también usa el comando git mv, pero el destino del archivo no es el mismo directorio del archivo movido.

1
usuario@mi-pc:~ $ git mv test1_rename.txt move/test1.txt

Aquí, move es el directorio de destino, y test1.txt es el nuevo nombre del archivo movido test1_rename.txt.

Compruebo el git status,

1
2
3
4
5
6
usuario@mi-pc:~ $ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	renamed:    test1_rename.txt -> move/test1.txt

Como se puede ver, también es una operación renamed, pero con un destino diferente.

Modificar el último commit hecho

Aveces se da el caso de necesitar modificar el último commit por que encontramos una errata u otros pequeños fallos en el código. Podría revisar el código y hacer otro commit en el repositorio de nuevo. Pero también puedo reescribir la última confirmación añadiéndoselos .

La bandera --amend después de git commit le dice a git que esta confirmación reemplazará la anterior que ya no estará en su rama de trabajo.

1
usuario@mi-pc:~ $ git commit --amend -m "new information is updated"

Nota: nunca se debe modificar una confirmación que no sea la más reciente, porque otro miembro del equipo u otras ramas tienen la versión basada en esa confirmación. Después de modificar, pierden su punto de referencia y es difícil recuperarle.

Eliminar un «commit»

Sirve por si algo ha fallado o se quiere eliminar:

1
usuario@mi-pc:~ $ git revert <sha del decommit>

Eliminar origen remoto

Primero debo saber la referencia a el origen a eliminar, para lo cual listo todos los que disponga en el repositorio local con el siguiente comando:

1
git remote -v

Para eliminar un origen remoto, necesito eliminar su referencia en mi repositorio local. Al eliminar un origen remoto se eliminará el origen remoto y todos sus datos del repositorio local. Ejecuto el siguiente comando.

1
git remote rm <remote>

Aquí <remote> es el nombre del origen remoto que quiero eliminar.

Por ejemplo, para eliminar el origen remoto origin:

1
git remote rm origin

Después de eliminar un origen remoto, puedo volver a agregarlo a través del siguiente comando:

1
git remote add origin your_Remote_Url

luego ejecuto:

1
git push -u origin master

Con ello configuro la rama master para hacer seguimiento a la rama remota master desde la url contenida en origin.

Un ejemplo práctico es:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Enrique@esc-pc:~/repositorios_github/esaborit.github.io
$ git remote -v
origin	https://github.com/esaborit/esaborit.github.io.git (fetch)
origin	https://github.com/esaborit/esaborit.github.io.git (push)
Enrique@esc-pc:~/repositorios_github/esaborit.github.io
$ git remote rm origin
Enrique@esc-pc:~/repositorios_github/esaborit.github.io
$ git remote -v
Enrique@esc-pc:~/repositorios_github/esaborit.github.io
$ git remote add origin git@github.com:esaborit/esaborit.github.io.git
Enrique@esc-pc:~/repositorios_github/esaborit.github.io
$ git remote -v
origin	git@github.com:esaborit/esaborit.github.io.git (fetch)
origin	git@github.com:esaborit/esaborit.github.io.git (push)
Enrique@esc-pc:~/repositorios_github/esaborit.github.io
$ git push -u origin master
Enter passphrase for key '/home/Enrique/.ssh/id_rsa': 
Enumerando objetos: 328, listo.
Contando objetos: 100% (328/328), listo.
Compresión delta usando hasta 4 hilos
Comprimiendo objetos: 100% (213/213), listo.
Escribiendo objetos: 100% (238/238), 10.42 MiB | 4.75 MiB/s, listo.
Total 238 (delta 86), reusado 30 (delta 0), pack-reusado 0
remote: Resolving deltas: 100% (86/86), completed with 45 local objects.
To github.com:esaborit/esaborit.github.io.git
   8607447..04c3477  master -> master
Rama 'master' configurada para hacer seguimiento a la rama remota 'master' de 'origin'.
Enrique@esc-pc:~/repositorios_github/esaborit.github.io
$ 

De esta forma he conseguido actualizar el origen del repositorio remoto pasando de https a ssh

1
2
3
https://github.com/esaborit/esaborit.github.io.git 

git@github.com:esaborit/esaborit.github.io.git

Tambien se puede hacer utilizando un solo comando

1
2
3
git remote set-url origen_a_cambiar newUrl 
# Por ejemplo
git remote set-url origin git@github.com:esaborit/esaborit.github.io.git

Otros comandos

1
2
usuario@mi-pc:~ $ git log
usuario@mi-pc:~ $ git log -p

Sirve para ver los commits fusionados y ver sus sha. El segundo aparte de del commit también me muestra los cambios.

1
usuario@mi-pc:~ $ git reset --hard HEAD~1

Esto revierte el último commit que he echo antes de hacer un push y borra los cambios producidos.

1
usuario@mi-pc:~ $ git reset --soft HEAD~1

Retrocede un commit, pero no borra ni pierdo los cambios, osea, que saldrá como si estuviera pendiente de hacer el commit, bastante útil para hacer cambios de última hora.

En ambos, una vez hecho push, no queda mas remedio que hacer revert.

Conceptos de main , origin y HEAD.

HEAD es un nombre que se refiere siempre al commit en el que tenemos posicionado el repositorio en el momento actual. Independientemente de la rama en la que estemos, de cómo se llame la rama principal o el repositorio principal remoto.

main la rama predeterminada que se crea automáticamente cuando se crea un repositorio.

Nota: hasta mediados del año 2020 esta rama se llamaba “master” y no “main”.

Por regla general a main se la considera la rama principal y la raíz de la mayoría de las demás ramas. Lo más habitual es que en main se encuentre el “código definitivo”, que luego va a producción, y es la rama en la que se mezclan todas las demás tarde o temprano para dar por finalizada una tarea e incorporarla al producto final.

Esta manera de trabajar con ramas nos permite llevar en paralelo varios desarrollos relacionados sin importar que cada uno de ellos termine en momentos muy diferentes, ya que no interfieren, pudiendo mezclarlos todos al final.

Lo más habitual es que para poder mezclar otra rama cualquiera con main haya que pedir permiso y que alguien lo revise todo antes de permitirlo. Es lo que se denomina un “pull request”. O simplemente que la rama main se encuentre protegida de modo que solo si se pasan todos los test y aseguramos que el producto funciona, sea posible mezclarse con ella. De este modo impedimos que cualquiera pueda llevar al producto final código que no cumple unos mínimos de calidad.

origin es simplemente el nombre predeterminado que recibe el repositorio remoto principal contra el que trabajamos. Cuando clonamos un repositorio por primera vez desde GitHub o cualquier otro sistema remoto, el nombre que se le da a ese repositorio “maestro” es precisamente origin

Hacer un pull sin especificar cómo reconciliar las ramas es poco recomendable

1
usuario@mi-pc:~ $ git config --global pull.rebase false

Inspecciono el repositorio remoto con el comando $ git remote show origin.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
usuario@mi-pc:~ $  git remote show origin
* remoto origin
  URL  para obtener: https://github.com/esaborit/prueba.git
  URL para publicar: https://github.com/esaborit/prueba.git
  Rama HEAD: master
  Ramas remotas:
    experimental rastreada
    master       rastreada
  Ramas locales configuradas para 'git pull':
    experimental fusiona con remoto experimental
    master       fusiona con remoto master
  Referencias locales configuradas para 'git push':
    experimental publica a experimental (actualizado)
    master       publica a master       (actualizado)

El comando lista la URL del repositorio remoto y la información del rastreo de ramas. El comando te indica claramente que si estás en la rama maestra y ejecutas el comando git pull, automáticamente combinará la rama maestra remota con tu rama local, luego de haber traído toda la información de ella. También lista todas las referencias remotas de las que ha traído datos.

Este comando te indica a cuál rama enviarás información automáticamente cada vez que ejecutas git push, dependiendo de la rama en la que estés. También te muestra cuáles ramas remotas no tienes aún, cuáles ramas remotas tienes que han sido eliminadas del servidor, y varias ramas que serán combinadas automáticamente cuando ejecutes git pul.

Cuando hacemos git pull, nos traemos los cambios del repositorio que elijamos o tengamos configurado, y uno de los parámetros que podemos utilizar es rebase:

1
git pull --rebase

¿Qué hace esto? Al realizar un pull estamos haciendo un fetch y justo después un merge, pasándole la opción rebase, git intentará traer todos los cambios y después aplicar nuestras modificaciones encima en lugar de intentar hacer un merge desde el punto en el que estábamos, esto hará que nuestro histórico tenga mucho mejor aspecto.

Nota: Git no siempre va a poder hacer git pull --rebase, por descontado si hay conflictos, no sobreescribe el código sino que nos dejará editar y entonces forzará hacer un merge manual.

Fuentes

https://www.atlassian.com/es/git/tutorials/what-is-git

https://git-scm.com/book/es/v2/Fundamentos-de-Git-Obteniendo-un-repositorio-Git

https://www.w3schools.com/git/default.asp?remote=gitlab

https://desarrolloweb.com/articulos/trabajar-ramas-git.html

https://desarrolloweb.com/manuales/manual-de-git.html

https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line

https://instatecno.com/aprender-git-github-gitlab-bitbucket/