Post

GitHub

Alt text

Git: Sistema de Control de Versiones

¿Qué es Git?


Git (abreviación de “Global Information Tracker”) es un sistema gratuito y de código abierto para el control de versiones que te permite seguir los cambios realizados en tu código. Fue creado por Linus Torvalds en 2005 y se utiliza ampliamente en el desarrollo de software.

Características clave de Git


  • Control de Versiones: Git registra todos los cambios realizados en tu código, lo que te permite revertir a una versión anterior si es necesario.
  • Sistema Distribuido: Git es un sistema distribuido, lo que significa que cada desarrollador trabajando en un proyecto tiene una copia local del historial completo del proyecto.
  • Repositorio Local: Cada desarrollador trabaja con un repositorio local (o “repo”) que contiene todos los archivos y el historial del proyecto.

¿Cómo funciona Git?


  1. Inicia un Repositorio: Creas un nuevo repositorio de Git ejecutando git init en tu terminal.
  2. Añade Archivos al Área de Preparación: Añades archivos a la área de preparación (también conocida como el “índice”) utilizando git add <archivo> o git add ..
  3. Realiza un Commit: Realizas un commit con los cambios que has hecho en tu repositorio local utilizando git commit -m "mensaje de commit".
  4. Envía Cambios a un Repositorio Remoto: Envías tus cambios comitidos a un repositorio remoto (como GitHub) utilizando git push origin master.

Flujo de Trabajo de Git


  1. Crea una Rama: Crea una nueva rama para una característica o corrección de errores utilizando git branch <rama-name>.
  2. Realiza Cambios: Realizas cambios en los archivos en tu repositorio local.
  3. Comita y Envía: Haces un commit en tus cambios y las envías a un repositorio remoto.
  4. Merges: Haces un merge tus cambios en la rama principal (generalmente llamada “master”) utilizando git merge <rama-name>.

GitHub: Plataforma Web para Git

¿Qué es GitHub?


GitHub es una plataforma web que te permite alojar y administrar tus repositorios de Git. Fue creada en 2008 por Chris Wanstrath, Scott Chasen y Tom Preston-Werner.

Características clave de GitHub


  • Repositorios en la Nube: GitHub alberga tus repositorios de Git en la nube.
  • Herramientas de Colaboración: GitHub proporciona características para la colaboración, como seguimiento de problemas, solicitudes de incorporación y revisión de código.
  • Proyectos de Código Abierto: GitHub es hogar de muchos proyectos de código abierto.

¿Cómo funciona GitHub?


  1. Crea un Repositorio: Creas un nuevo repositorio en GitHub haciendo clic en el botón “Nuevo”.
  2. Clona el Repositorio: Clonas el repositorio a tu máquina local utilizando git clone <url-del-repositorio>.
  3. Realiza Cambios: Realizas cambios en los archivos en tu repositorio local.

Iniciamos la configuración

Vamos a empezar configurando varias variables necesarias para trabajar un poco más cómodo:

1
2
3
git config --global user.email          "corre@example.com"
git config --global user.name           "Tu nombre y apellidos"
git config --global init.defaultBranch  main

Creamos un directorio

1
2
mkdir prueba
cd prueba

Comprobamos que tenemos el directorio vacío

1
ls -la

Inicializamos el repositorio

1
git init

Comprobamos que se ha creado el directorio .git

1
ls -la

Creamos un archivo README.md y ponemos nuestro nombre

Este archivo será el que se leera por defecto en GitHub

1
echo "Mi nombre" > README.md

Registramos los cambios en el repositorio

  1. Añadimos el área de preparación
    1
    
    git add README.md
    
  2. Añadimos al repositorio en local
    1
    
    git commit -m "Primer cambio registrado"
    

Añadimos dos líneas más

Cada vez que se añada una línea tenemos que hacer un commit cambiando la información 2ª línea la fecha de hoy 2ª AXúquer

Por último vemos cambios realizados

Para ello ejecutamos

1
2
git  log
git  log  --oneline

Deberían aparecer 3 commits tal que así:

Alt text

Revisar commits realizados

En la actividad siguiente, haremos uso del comando git checkout para movernos por los distintos commits .

Antes de nada comprueba que tienes al menos 3 commits realizados. Para ello ejecuta:

1
git  log  --oneline --all

Alt text

La opción –oneline, nos muestra la información de cada commit en una línea.

La opción –all, nos muestra todos los commits.

La primera columna es un hash, un identificador.

Los números no están ordenados. En mi caso, el primer commit tiene un hash 55b9b0b. El último commit mio es el ba90153. Tú tendrás otro hash distinto. No te preocupes, es así.

La segunda columna es el mensaje que pusimos cuando hicimos el commit.

Fíjate también que en el último commit, en mi caso ba90153, existe un identificador HEAD. Ésta es una referencia que apunta al commit en el que estamos situados en el momento actual. Además aparece otro identificador main, que indica en la rama en la que estamos. Por defecto, siempre es main.

El identificador main siempre apunta al último commit de la rama. Sin embargo el identificador HEAD podemos moverlo y desplazarmos entre distintos commit y ver como estaban los archivos en cada momento.

Para mover el identificador HEAD utilizamos el comando git checkout numero_hash.

Realiza los siguientes pasos:

1. Vamos a ver el contenido del archivo README.md en el commit actual.

Para ello hacemos:

1
cat  README.md

Deben aparecer 3 líneas de texto: tu nombre, la fecha y el nombre del centro AXúquer.

2. Vamos a movernos al primer commit.

Para ello hacemos:

1
git  checkout  55b9b0b

Tú deberás poner el hash que tengas.

Te aparecerá un mensaje que contiene “Te encuentras en estado ‘detached HEAD’”. Esto indica que la referencia HEAD no está al final de la rama. No te preocupes por ello.

Ahora veamos el contenido del archivo README.md.

1
cat README.md

Debe aparecer sólo una línea con tu nombre. Es el contenido que tenía dicho archivo en ese commit.

3. Veamos en que posición de la rama nos encontramos. Para ello ejecutamos:

1
git  log  --oneline --all

Fíjate donde apunta la referencia HEAD en este momento.

Algo que quizás te haya pasado desapercibido pero que es extremadamente IMPORTANTE es que cada vez que nos movemos de un commit a otro, el contenido del directorio de trabajo cambia. Esto lo hace git de forma automática.

NO REALIZAREMOS ningún cambio a los archivos, sólo vamos a echar un vistazo.

4. Vamos a movernos al segundo commit.

Para ello hacemos:

1
git  checkout  9ca2b54

Tú deberás poner el hash que tengas. No es necesario poner todos los dígitos, con cuatro será suficiente.

Ejecuta

1
cat README.md

y haz una captura de pantalla.

Deberían aparecer 2 líneas: tu nombre y la fecha.

5. Vuelve a hacer

1
git  log  --oneline --all

Y comprueba que HEAD está en el segundo commit.

6. Por último,

para volver al último commit de la rama master, simplemente hacemos:

1
git checkout main

Podemos ver que todo está en su sitio haciendo

1
git  log  --oneline --all

NOTA: No borrar el repositorio local. Lo volveremos a utilizar en la siguiente actividad.

Etiquetar commits y ver diferencias

En esta actividad vamos a ver 3 comandos:

  • git tag
  • git show
  • git diff

El primer comando (git tag) nos permite poner etiquetas a los commits. No se etiquetan todos los commits, solo las releases que deseemos.

Los 2 siguientes (git show y git diff) son para ver los cambios realizados entre distintos commits. Son muy parecidos aunque con pequeñas diferencias.

Básicamente git show nos permite ver los cambios de un commit respecto al anterior, mientras que git diff nos permite ver cambios en un rango de commits.

De todas formas tanto git show como git diff tienen tantas opciones que aquí sólo nos centraremos en las esenciales.

Empecemos:

1. Etiquetamos el commit primero y el tercero.

El primer commit será la versión 1 de nuestro proyecto. La etiqueta será v1.

El tercer commit será la versión 2 de nuestro proyecto. La etiqueta será v2.

El segundo commit no será etiquetado.

Para etiquetar utilizamos el comando

1
git  tag  -a  nombre_etiqueta  -m  "Mensaje"   commit_a_etiquetar

Por ejemplo, en mi caso:

1
2
git tag  -a v1  -m "Primera versión estable"  55b9
git tag  -a v2  -m "Versión 2"  fdeb

La opción -a significa annotate.

La opción -m nos permite poner un mensaje.

Finalmente debemos poner el commit al que deseamos aplicar la etiqueta.

Si por cualquier motivo nos equivocamos al crear la etiqueta podemos eliminarla con

1
git tag -d nombre_etiqueta

2. Usando etiquetas para movernos

Las etiquetas nos permiten referenciar commits de una forma más cómoda que usando el identificador de hash.

Por ejemplo es más cómodo usar:

1
git checkout v1

Que usar:

1
git checkout 55b9

Para volver al último commit haz:

1
git checkout main

3. Examinado cambios de un commit respecto al anterior.

Para ver los cambios introducidos respecto al commit anterior hacemos:

1
git show

Alt text

En este caso, al coincidir todos los apuntadores (HEAD, master, v2 y ba90) al mismo sitio, el comando anterior es equivalente a:

1
2
3
4
git show HEAD
git show master
git show ba90
git show v2

Como podemos observar, se añadió una línea, la que contiene AXúquer.

Las líneas añadidas aparecen en verde y con un signo +.

Las líneas eliminadas aparecen en rojo y con un signo -.

En este caso solo hemos realizado operaciones de adición.

Para ver el cambio realizado en el commit segundo respecto al primero, hacemos

1
git show 9ca2

Debe aparecer añadida la línea con la fecha.

Y para ver el cambio realizado en el commit primero respecto al repositorio vacío, hacemos:

1
git show v1

Debe aparecer añadida la línea con el nombre.

4. Examinado cambios de un commit respecto a varios anteriores.

Si deseamos ver todos los cambios realizados a lo largo de varios commits, haremos uso de git diff.

La forma de uso es

1
git  diff  commit1..commit2

Por ejemplo, para ver los cambios entre la versión 1 y la versión 2, hacemos

1
git  diff  v1..v2

Podemos ver que se han añadido 2 líneas desde el commit v1.

Es muy aconsejable poner primero el commit más antiguo y después el commit más moderno. Si lo hacemos al contrario, el resultado en lugar de aparecer en color verde aparecerá en color rojo, y su interpretación será más confusa.

5. Diferencia entre git show y git diff

También podemos hacer

1
git show v1..v2

Alt text

NOTA: No borrar el repositorio local. Lo volveremos a utilizar en la siguiente actividad.

Crear repositorio remoto y subir commits locales

En esta actividad crearemos un repositorio vacío en GitHub y subiremos el contenido de nuestro repositorio local.

1. Primero, creamos un repositorio totalmente vacío en GitHub.

Accedemos a nuestra cuenta de GitHub.

En la esquina superior derecha, pulsamos en el signo + y luego en New repository

Escogemos el nombre del repositorio. No tiene por que coincidir con el nombre del repositorio local, aunque es lo aconsejable para no hacernos un lío.

Es muy importante que NO INICIALICES EL REPOSITORIO. Si el repositorio no estuviese vacío podría darnos un conflicto.

En una actividad posterior crearemos conflictos y veremos como resolverlos. Pero en en esta actividad, sólo vamos a trabajar lo básico.

Pulsaremos en Create Repository y nos aparecerá una página en la cual nos pondrá varias opciones de inicializar el reposiotrio:

Escogemos la imagen que pone únicamente git remote y git push

Ahí podemos ver la URL del repositorio remoto. Hay 2 formas de acceso:

  • mediante HTTPS
  • mediante SSH

Usaremos, por ahora, HTTPS. En una actividad posterior veremos como usar SSH y utilizar cifrado público-privado para no tener que introducir cada vez nuestras credenciales.

Más abajo se indican los comandos a ejecutar en nuestro repositorio local. Lo vemos en el siguiente punto.

Para tu comodidad, no cierres la página. Más adelante volveremos a ella.

2. Asociar repositorio local con repositorio remoto

En nuestro repositorio local, para asociarlo con el repositorio remoto, hacemos:

1
git remote add origin  ** Tu enlace **

Nuestro repositorio remoto será identificado como origin. Podemos ponerle otro nombre, pero no debemos. Es una convención ampliamente aceptada poner este nombre al repositorio remoto de GitHub.

Para ver si se ha añadido bien hacemos

1
git remote -v

Deben aparecer 2 entradas, una para bajada (fetch) y otra para subida (push)

NOTA: Si por cualquier motivo nos equivocamos y escribimos mal el nombre o la URL, podemos borrar la asociación con

1
git remote remove origin

y luego volver a crear la asociación.

3. Subir todos los commits locales al repositorio remoto

Para subir el contenido de nuestro repositorio local al repositorio remoto hacemos:

1
git push -u origin main

El identificador origin es el nombre que dimos a nuestro vínculo. El identificador main se refiere a la rama principal.

Es una convención ampliamente seguida, así que respétala.

Se nos pedirá nuestro usuario y contraseña. Lo introducimos, y si no hay problema, se realizará la subida.

4. Comprobando la subida.

Volvemos a la página de GitHub y la actualizamos.

Nos aparecerá dentro de nuestro repositorio nuestro archivo README.md

GitHub ofrece muchas funcionalidades.

Así que nos centraremos ahora mismo en las releases. Estás se corresponden con el etiquetado que realizamos en la actividad anterior con git tag.

Teníamos 2 releases, etiquetadas como v1 y v2, pero sin embargo aquí no aparece ninguna.

El motivo, es que debemos subir las etiquetas por separado con el comando

1
git push --tags

Así que ejecutaremos dicho comando desde nuestro repositorio local. Refrescaremos la página. Et voilà !

5. Examinando commits y releases en GitHub.

Pulsa en 3 commits y haz una captura de pantalla. Por tu cuenta puedes examinar cada uno de los commits.

Pulsa en 2 releases y haz una captura de pantalla. Observa que se han creado archivos comprimidos con el código fuente para descargar.

NOTA: No borrar los repositorio local ni repositorio remoto. Los volveremos a utilizar en la siguiente actividad.

Deshacer cambios en repositorio local

En esta actividad, veremos que podemos hacer cuando cometemos errores.

Si realizamos algún cambio y hemos “metido la pata”, podemos deshacer el “entuerto”.

Vamos a verlo de forma práctica haciendo uso del comando git reset –hard

1. Deshacer cambios en el directorio de trabajo

Estando en el último commit de la rama master, modificamos el archivo README.md

Vamos a eliminar las 2 últimas líneas.

1
nano README.md

Editamos. Debe quedar una sola línea con nuestro nombre.

Para ver los cambios que hemos introducido ejecutamos:

git diff HEAD

Es decir vamos a ver las diferencias que existen en nuestro directorio de trabajo respecto al commit HEAD, es decir el último commit confirmado.

NOTA: Si quisiesemos ver las diferencias de nuestro directorio de trabajo respecto al commit de la Versión 1, haríamos git diff v1. Observa que estamos viendo las diferencias hacia al pasado. Esta forma de uso de git diff es diferente a la que vimos en la última actividad, en la cual veíamos las diferencias hacia el futuro.

Se ve claramente que hemos eliminado las 2 últimas líneas.

Para volver el estado de este archivo y de CUALQUIER OTRO de nuestro directorio de trabajo que hayamos modificado, ejecutamos:

git reset --hard

2. ¿Y para deshacer el área de preparación?

Imaginemos que hemos ido un poco más lejos, y que además de modificar el directorio de trabajo, hemos añadido los cambios al Staging Area. Es decir hemos hecho

1
nano README.md

Borrado las 2 últimas líneas.

Y luego hemos añadido al área de preparación mediante

1
git  add  README.md

No te preocupes en este caso puede también aplicarse el comando anterior:

1
git  reset --hard

Dicho comando coge el contenido que hay en nuestro commit confirmado y recupera ambos: el directorio de trabajo y el área de preparación.

3. ¿Y qué pasa si ya realicé un commit?

Imaginemos que hemos ido todavía un poco más lejos, y que además de modificar el directorio de trabajo y añadir los cambios al Staging Area, hemos realizado un commit. Es decir hemos hecho

1
nano README.md

Borrado las 2 últimas líneas.

Y luego hemos añadido al área de preparación mediante

1
git  add  README.md

Y además hemos hecho

1
git commit -m "Borras líneas de README.md"

Pues en este caso también podemos usar el comando git reset –hard de la siguiente forma:

git reset --hard HEAD~1

HEAD~1 significa el commit anterior al actual. Es decir un commit hacia atrás.

HEAD~2 significa 2 commits hacia atrás.

HEAD~n significa n commits hacia atrás, sustituyendo n por un número.

NOTA: Usar git reset –hard de esta última forma es peligroso, porque perdemos el último o últimos commits. Así que hay que asegurarse muy bien de que es eso lo que queremos.

NOTA: No borrar los repositorio local ni el remoto. Los volveremos a utilizar en la siguiente actividad.

Archivo .gitignore

En esta actividad empezaremos a trabajar con algo más real. Por ejemplo, una sencilla aplicación de Java. Esta actividad también es práctica.

Vamos a seguir utilizando el repositorio que estabamos usando en las actividades anteriores.

git log --oneline --all

1. Creamos una aplicación HolaMundo en Java.

Creamos la aplicación y después continuamos…

Si ahora volvemos a hacer un listado, veremos que nos ha creado una nueva carpeta llamada build con el bytecode resultante de la compilación.

2. Añadiendo archivos al repositorio local

Como vimos en la actividad anterior, si ahora ejecutamos git diff HEAD, esperariamos ver los cambios de nuestro directorio de trabajo respecto al último commit.

Sin embargo esto no es lo que ocurre. NO SE MUESTRA NADA. ¿Por qué es esto?

Esto es porque git diff HEAD funciona siempre teniendo en cuenta los archivos que ya habían sido añadidos previamente al repositorio. Es decir sólo tiene en cuenta los archivos con seguimiento.

Los archivos nuevos son archivos sin seguimiento. En este caso debemos usar git status para ver esta circunstancia.

Ahora debemos añadir todos estos archivos al área de preparación (Staging Area) y luego realizar un commit.

PERO ESPERA UN MOMENTO. Voy a explicarte algo.

Cuando se trabaja con proyectos de código fuente existen algunos archivos que no interesa añadir al repositorio, puesto que no aportan nada. En el repositorio, como norma general, no debe haber archivos ejecutables, ni bytecode, ni código objeto, y muchas veces tampoco .zip, .rar, .jar, .war, etc. Estos archivos inflan el repositorio y, cuando llevamos muchos commits, hacen crecer demasiado el repositorio y además pueden ralentizar el trabajo de descarga y subida.

Para cada lenguaje y para cada entorno de desarrollo se recomienda no incluir ciertos tipos de archivos. Son los archivos a ignorar. Cada programador puede añadir o eliminar de la lista los que considere adecuados. Los archivos y carpetas a ignorar deben indicarse en el archivo .gitignore. En cada línea se pone un archivo, una carpeta o una expresión regular indicando varios tipos de archivos o carpetas.

En el repositorio https://github.com/github/gitignore tienes muchos ejemplos para distintos lenguajes, herramientas de construcción y entornos.

Para el lenguaje Java: https://github.com/github/gitignore/blob/master/Java.gitignore

Para la herramienta Gradle: https://github.com/github/gitignore/blob/master/Gradle.gitignore

Para el entorno Netbeans: https://github.com/github/gitignore/blob/master/Global/NetBeans.gitignore

Simplificando, nosotros vamos a ignorar las carpetas que creás oportunas. Entonces, el archivo .gitignore debe tener el siguiente contenido:

1
2
3
4
el directorio que queramos/
el archivo que queramos
el .directorio que queramos/
...

La barra final es opcional, pero a mí me gusta ponerla cuando me refiero a carpetas, para así saber cuando se trata de un archivo y cuando de una carpeta.

Crea el archivo .gitignore con dicho contenido y haz una captura de pantalla.

Ahora si hacemos

git status

veremos que no nos aparecen las carpetas que habéis elegido. Y nos aparece un archivo nuevo .gitignore.

Ahora ya podemos ejecutar

1
2
git add .
git commit -m "Código fuente inicial"

Fíjate que he escrito git add .. El punto indica el directorio actual, y es una forma de indicar que incluya en el área de preparación todos los archivos del directorio en el que me encuentro (salvo los archivos y carpetas indicados en .gitignore) Se utiliza bastante esta forma de git add cuando no queremos añadir los archivos uno a uno.

3. Subir cambios de repositorio local a repositorio remoto

Ya sólo nos queda subir los cambios realizados al repositorio remoto con git push

Para hacer algo más interesante este apartado, vamos a crear una etiqueta en el commit actual y subirla a github para que éste cree una nueva release.

1
2
git tag v3
git push --tags

Bueno, las etiquetas v1 y v2 no se suben porque ya la habíamos subido previamente.

En este caso, podríamos también haber ejecutado

git push origin v3

Y la historia de nuestro repositorio local nos quedaría…

Accede a tu repositorio en GitHub y haz una captura de pantalla de las releases.

Haz otra captura de los archivos y carpetas de código subidas a GitHub. No deberían aparecer ni la carpeta build ni la carpeta .gradle. Y sí debería aparecer el archivo .gitignore.

NOTA: La carpeta .git nunca se muestra en GitHub.

NOTA: No borrar los repositorio local ni repositorio remoto. Los volveremos a utilizar en la siguiente actividad.

This post is licensed under CC BY 4.0 by the author.