logo git

Tutorial de Git

Introducción al software de control de versiones Git. Una guía práctica para trabajar con Git desde la terminal y desde el entorno de desarrollo Eclipse IDE. También aprenderemos a utilizar repositorios remotos en GitHub y a sincronizarlos con nuestro equipo local mediante credenciales de acceso por token.

¿Qué es Git?

Git es uno de los sistemas de control de versiones más utilizados por los desarrolladores de software. Fue creado por Linus Torvalds y lanzado en 2005.

Un sistema de control de versiones es una herramienta que permite gestionar las distintas actualizaciones y modificaciones realizadas en el código. Su principal función es registrar los cambios en una línea de tiempo, lo que facilita volver a versiones anteriores si algo no funciona como se esperaba. Otra característica clave es la posibilidad de crear ramas secundarias del proyecto, en las que pueden trabajar diferentes miembros del equipo. Una vez que su trabajo está finalizado, estas ramas pueden fusionarse con la rama principal.

Al trabajar con Git, nuestro proyecto se encuentra, como mínimo, en dos ubicaciones: una copia local en el ordenador de uno de los desarrolladores y una copia remota en un servidor de repositorios. Algunos de los servicios más conocidos que alojan repositorios Git son GitHub, GitLab, Bitbucket y SourceForge.

El siguiente esquema ayuda a entender cómo funciona Git. Se representa una estructura local dividida en tres partes:

  1. Directorio de trabajo: contiene los archivos y carpetas del proyecto.
  2. Área de preparación (Staging Area): una zona intermedia donde se organizan los cambios antes de confirmarlos en el repositorio local (git add).
  3. Repositorio local: almacena los cambios confirmados antes de enviarlos al servidor remoto (git commit).

En la parte derecha del esquema, se encuentra la zona del servidor, donde se suben los repositorios (git push) y desde donde también se pueden clonar en local (git clone).

Esquema de Git
Crear un proyecto git

Explicado de manera resumida, para empezar a trabajar con Git, debemos crear un nuevo repositorio localmente (con los comandos git add y git commit) y, en el servidor (GitHub u otro), subir los archivos con git push.

Otra posibilidad es utilizar un repositorio que ya contiene contenido. En este caso, al clonarlo en el espacio de trabajo con git clone, se copiará todo el árbol de archivos del proyecto en nuestro ordenador.

Hasta ahora, hemos hablado de un proyecto hipotético con un único desarrollador y una sola rama de trabajo. Sin embargo, lo habitual es que los repositorios tengan múltiples ramas. Un caso común es contar con una rama principal de desarrollo (generalmente llamada main) y otras ramas secundarias destinadas a desarrollo, pruebas, distintos equipos de trabajo, etc. Hay numerosos casos en los que se pueden aplicar ramas secundarias.

Cuando el contenido de una rama está finalizado y se desea integrar en la rama principal, se fusiona con git merge, pasando a formar parte de la rama principal. De esta manera, se trabaja sobre copias del proyecto, protegiendo el código original.

Además de la línea de comandos, es posible utilizar clientes gráficos para Git, los cuales facilitan la visualización de la evolución de las ramas y permiten realizar muchas operaciones sin necesidad de memorizar comandos. Algunos ejemplos son SourceTree, GitHub Desktop, SmartGit y GitKraken.

Esquema de Git

Desde el entorno de desarrollo también es posible gestionar Git directamente desde los principales IDEs que lo integran en sus menús, como Eclipse, VS Code, IntelliJ IDEA o NetBeans, por citar algunos muy conocidos.

Quiero usar git. ¿Cómo empiezo?

Desarrollar un ejemplo ayudará a entenderlo mejor. Vamos a crear un mini proyecto y hacer las operaciones más comunes con git.

Crear repositorio remoto en GitHub

Necesitamos crear una cuenta de usuario en un servidor de repositorios y a continuación crear un nuevo proyecto en blanco. En este pequeño tutorial usaré https://github.com para crear un repositorio llamado "demoRepositorio". Si no tienes cuenta de usuario en github puedes crearte una gratuitamente.

github nuevo

Pulsando el botón "Create Repository" se crea el repositorio vacío en el lado servidor. Para más sencillez a la hora de subir los archivos al repositorio, es recomendable no marcar aquí la opción de crear los archivos README.MD y .gitignore porque tendremos un error de conflicto de historial entre nuestro repo local y el remote. Esto ocurre porque Git detecta que la rama main en el remoto tiene historial de commits diferente al de tu rama local. No te preocupes si no entiendes ahora que es una rama ni un commit. Lo sabrás enseguida.

El error mostrado al subir los archivos con el comando push podría ser como este:

error: failed to push some refs to 'https://github.com/agriarte/demoRepositorio.git'  

En este primer repositorio (y en la mayoría de los casos, es la opción más común), tomaremos como guía de referencia los comandos dentro del bloque create a new repository on the command line. Se trata de una serie de comandos de Git que inician un repositorio en la carpeta local y lo vinculan al repositorio en el servidor.

comandos github nuevo

Si has llegado hasta aquí, ya tienes el repositorio nuevo y vacío https://github.com/agriarte/demoRepositorio, al que podrás subir un proyecto cuando habilites los permisos de repositorio correspondientes.

Generar Fine-grained token

Siguiendo los consejos de la lista anterior, he creado un Fine-grained token nombrado "Tutorial" para poder identificarlo fácilmente en mi lista de tokens creados:

Este token solo permite gestionar el repositorio del tutorial durante 1 mes:

Dentro del apartado "Repository permissions", le asigno permisos de lectura y escritura en Contents (código) y Pull Requests (gestión de merges):

Al pulsar el botón Generate Token, se mostrará el token una sola vez. Deberemos copiarlo y guardarlo en un lugar seguro. Si lo perdemos o caduca, tendremos que generar uno nuevo.

Instalar Git y crear nuevo proyecto local

Desde https://git-scm.com, puedes obtener información sobre la instalación de Git en todos los sistemas y acceder a la documentación oficial.

En Windows, Git también instala una consola de comandos Bash para ejecutar sus comandos, ya que el terminal CMD no es completamente compatible. Si usas VS Code, puedes utilizar su terminal integrada, la cual funciona correctamente con Git. También se instala un programa con interfaz gráfica para usar Git, pero no lo veremos en este tutorial. Si te interesa, siéntete libre de explorarlo y usarlo si te resulta útil.

Una vez instalado Git, es recomendable , y en muchos casos necesario, configurar nuestro nombre y correo electrónico en el archivo de configuración. Aunque no es estrictamente obligatorio para usar Git, sí lo es para poder realizar commits correctamente, ya que esta información se usa para identificar a cada desarrollador en el historial de cambios del proyecto.

git config --global user.name "Nombre Apellido" #Configura tu nombre.
git config --global user.email "ejemplo@email.com" #Configura tu email.
git config --list #Muestra la configuración actual de Git.

A continuación, creamos una nueva carpeta que servirá como directorio de trabajo de Git. Aquí es donde queremos crear o clonar el repositorio. Para abrir la consola en esta carpeta, haz clic derecho dentro de ella y selecciona "Git Bash Here" en el menú contextual. Esto abrirá una terminal directamente en el directorio del proyecto. Si no lo hacemos así, al abrir la consola manualmente, será necesario navegar hasta el directorio usando los comandos cd y ls.

Al tratarse de un nuevo proyecto, podemos seguir las instrucciones de GitHub y ejecutar los comandos del bloque "or create a new repository on the command line" que vimos al crear el repositorio en GitHub.

  • echo "# demoRepositorio" >> README.md Este comando no es propio de Git; echo es un comando de impresión que, en este caso, redirige el texto a un archivo. Si el archivo no existe, lo crea. Esta línea crea un archivo README.md en el directorio actual, que también es nuestro directorio de trabajo. En GitHub, este archivo servirá como la descripción del repositorio, donde podemos incluir instrucciones y cualquier otra información relevante sobre el proyecto.
  • git init Este comando se ejecuta solo una vez para inicializar un repositorio Git. Al ejecutarlo, se crea un subdirectorio oculto llamado .git, donde se almacenan los datos de configuración del repositorio.
  • git add README.md Los archivos que queremos rastrear se agregan con git add, lo que los mueve a la zona de preparación (staging area). Si se trata de archivos de texto, es posible que aparezca un mensaje de advertencia sobre la conversión de saltos de línea y retornos de carro, debido a diferencias entre Unix y Windows. Este ajuste no afecta el funcionamiento, por lo que podemos continuar sin problemas.
  • git commit -m "first commit"
    El comando git commit mueve los archivos rastreados al repositorio local. El parámetro -m permite añadir un mensaje descriptivo sobre el cambio. Tras ejecutar el commit, Git informa sobre los archivos registrados y genera un identificador único (hash) para esta versión. A medida que el proyecto avanza y realizamos nuevos commits, cada uno tendrá su propio hash, lo que nos permitirá movernos entre versiones.
  • git branch -M main Este comando cambia el nombre de la rama principal a main, en lugar de master, como recomienda GitHub.
  • git remote add origin https://github.com/agriarte/demoRepositorio.git
    Este comando establece la dirección del repositorio remoto, indicando dónde se almacenará el código en GitHub.
  • git push -u origin main El comando git push sube los archivos confirmados (committed) al repositorio remoto. En este caso, la instrucción significa: "Sube los archivos rastreados al servidor remoto en la rama main". Para Git, origin representa el repositorio remoto. Además, el parámetro -u establece la rama remota de seguimiento, lo que facilita el uso de git push en el futuro sin necesidad de especificar la rama y el repositorio remoto. En adelante, si queremos subir archivos al mismo destino ("origin"), podemos abreviar el comando a simplemente git push.

En este punto, ya tenemos un repositorio completamente creado. Podemos verificar que se ha subido correctamente accediendo a GitHub desde el navegador. En la página del repositorio, podremos ver todos los archivos, los commits realizados junto con sus identificadores (hashes), clonar el repositorio en otro ordenador y realizar muchas otras operaciones. Por ahora, no entraremos en demasiados detalles sobre GitHub.

También podemos utilizar comandos para obtener información sobre el historial del repositorio. Por ejemplo, con git log --oneline podemos ver un resumen de los commits realizados, mostrando cada uno en una sola línea con su identificador (hash) y su mensaje asociado.

A medida que trabajamos, iremos añadiendo los archivos con git add y confirmando los cambios con git commit en el repositorio local. Los archivos no se subirán al servidor hasta que ejecutemos git push. Vamos a verlo creando un archivo index.htm y observando las respuestas de los comandos git status y git status -s.

Vemos que Git detecta que hay un nuevo archivo index.htm sin seguimiento, junto con otra información sobre la rama en la que nos encontramos. Usa el color rojo y los símbolos ?? para indicar los archivos sin seguimiento. Ahora vamos a añadirlo al área de preparación (staging area) para ver qué sucede. Podemos usar git add index.htm o, de manera más corta, git add ., que añade todos los archivos sin seguimiento.

Los símbolos ?? se reemplazan por una A. La letra A proviene de "add".

Si modificamos el archivo index.htm y ejecutamos de nuevo git status, Git nos alertará de que hay cambios que no se han añadido. Aparecerá una M roja, que indica que el archivo ha sido modificado.

Para añadir los cambios, debemos ejecutar el comando git add .

A continuación, avanzamos al siguiente paso: realizaremos un commit de los cambios para actualizar el repositorio local. El comando es: git commit -m "nuevo index"

Ahora tenemos 2 commits, los cuales podemos identificar por su hash y mensaje de commit. Para subir estos cambios al servidor, repetimos el comando git push -u origin main.

Y con esto, el repositorio ya está disponible en GitHub.

Eliminar y modificar las etapas registradas

Cuando se está desarrollando código, puede ocurrir que estemos probando una parte nueva y no funcione como deseamos o, aún peor, que toda la aplicación deje de funcionar. En estas situaciones, usar Git puede salvarnos. Como vamos guardando el proyecto por fases mediante commits, siempre podemos volver a versiones anteriores o eliminar el commit más reciente para regresar al estado anterior.


Lo primero que debemos hacer es usar el comando git log --oneline para ver el historial de commits.

a3c9d3b (HEAD -> main) Tercer commit: añadimos archivo3.txt
7c9a1e2 Segundo commit: añadimos archivo2.txt
1f4c3b7 Primer commit: añadimos archivo1.txt

Si queremos retroceder a un punto anterior, por ejemplo, al segundo commit, podemos utilizar los comandos git checkout o git reset, dependiendo de si queremos conservar o eliminar los commits posteriores.

Si solo queremos revisar o trabajar temporalmente en una versión anterior sin modificar el historial, utilizamos checkout:

git checkout 7c9a1e2 # Retrocede temporalmente al segundo commit (modo detached HEAD)

Al retroceder a un estado anterior, salimos de la rama main. Debemos crear una nueva rama si queremos desarrollar código a partir de este punto, y fusionarla luego con main si es necesario.

Para volver a la rama main en su último estado, ejecutamos:

git checkout main

En cambio, si queremos volver de forma permanente a un estado anterior y eliminar los commits siguientes, usamos reset --hard:

git reset --hard 7c9a1e2 # Borra los commits posteriores y deja el repositorio en ese punto

Estas operaciones afectan únicamente al repositorio local. Si intentamos hacer push a GitHub tras un reset, obtendremos un error, ya que por seguridad, GitHub no permite sobrescribir el historial remoto por defecto.

! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'https://github.com/...'

Para evitar este error, debemos utilizar el parámetro --force al realizar el push:

git push origin main --force # Elimina los commits del historial remoto y lo reemplaza por el local

Ten en cuenta que esta operación puede eliminar cambios del repositorio remoto. Úsala con precaución, especialmente si trabajas en equipo.

Otros ejemplos útiles sobre este tema:

git reset --soft HEAD~1 → Elimina el último commit. El parámetro --soft hace que los archivos se borren del repositorio local, pero se mantengan en el directorio de trabajo. Si usamos --hard, también se borrarán los archivos del directorio de trabajo.

git reset --soft HEAD~2 → Elimina los dos últimos commits.

git reset --soft 3e4r2s → Elimina el commit con el ID especificado.

Si queremos eliminar archivos del stage area, podemos usar:

git rm --cached nombreArchivo → Borra un archivo específico del stage area, pero lo mantiene en el directorio de trabajo.

git reset → Borra todos los archivos del stage area, pero sin afectar su contenido en el directorio de trabajo.

Si solo queremos modificar el mensaje del último commit sin cambiar su contenido, utilizamos el parámetro --amend:

git commit --amend -m "Nuevo mensaje" → Reemplaza el comentario del último commit y genera un nuevo hash.

git commit --amend → Con esta instrucción también podemos modificar el mensaje de un commit existente. Sin embargo, la primera vez que se usa puede resultar poco intuitiva, ya que abrirá el archivo de configuración en el editor de Linux Vim.

Gitignore: La lista de archivos y carpetas que no queremos incluir nunca

En muchos proyectos, hay archivos que no queremos incluir en un repositorio. Puede ser por privacidad, como archivos que contienen credenciales de acceso a bases de datos, o porque no forman parte del código fuente, como las dependencias y librerías de algunos frameworks.

Para evitar que estos archivos sean rastreados por Git, se utiliza un archivo especial llamado .gitignore, que debe ubicarse en la raíz del directorio de trabajo.

Nota para usuarios de Windows: En Windows, no es posible crear archivos que comiencen con un punto desde el Explorador de archivos. Para solucionarlo, podemos usar el comando echo en la terminal:

echo "" >> .gitignore

Tras ejecutar este comando, se creará el archivo .gitignore. En él podemos listar los archivos y directorios que queremos excluir del control de versiones. Cada línea representa un elemento que Git ignorará. Si se trata de un directorio, se añade una barra / al final del nombre.

Ejemplo de .gitignore:

CarpetaPrivada/
conexionDB.php
*.log

Importante: Si un archivo ya ha sido agregado al repositorio antes de incluirlo en .gitignore, este no se eliminará automáticamente del control de versiones. Si ya hemos hecho git push, el archivo seguirá existiendo en el servidor, por lo que será necesario eliminarlo manualmente del historial si queremos que desaparezca.

Borrar un archivo de un repositorio público

Subir accidentalmente un archivo con contraseñas o información sensible a un repositorio público como Github puede ser una situación grave. Simplemente eliminarlo del directorio local, hacer un git commit y un git push no es suficiente, ya que el archivo seguirá estando en los commits anteriores. Incluso eliminarlo directamente desde GitHub no lo borrará del historial.

En estos casos, la opción más sencilla puede ser eliminar el repositorio por completo y volver a subir uno nuevo. Sin embargo, si queremos limpiar el historial sin eliminar el repositorio, podemos utilizar la herramienta BFG Repo-Cleaner o el comando git filter-branch.

Ejemplo: Borrar un archivo del historial de Git

Supongamos que hemos subido por error el archivo pagina2.htm y queremos eliminarlo por completo del repositorio. Usaremos el siguiente comando:

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch pagina2.htm' \ --prune-empty --tag-name-filter cat -- --all

Importante: Para evitar que el archivo vuelva a subirse accidentalmente en el futuro, debemos asegurarnos de agregarlo a .gitignore. Si aún no lo hemos hecho, lo editamos y realizamos un nuevo commit:

git commit -m "Añadir pagina2.htm a .gitignore"
Forzar la actualización en el servidor

Finalmente, ejecutamos los siguientes comandos para forzar la actualización del repositorio y limpiar cualquier rastro del archivo en el historial:

git push origin --force --all git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin git reflog expire --expire=now --all git gc --prune=now

Tras estos pasos, el archivo habrá desaparecido por completo de todos los commits del servidor.

Eliminar un archivo commiteado no sensible

Si lo que queremos eliminar es un archivo o directorio subido al repositorio que no tiene datos peligrosos de ser compartidos, porque hasta este momento no estaba no en la lista del .gitignore este método es mucho menos agresivo:

git rm -r --cached carpetaPrivada/
git commit -m "Eliminada carpetaPrivada del control de versiones"

Después de eso, .gitignore se encargará de que Git no la vuelva a seguir.

Ramas en Git

Hasta ahora hemos trabajado con un único flujo de desarrollo en una sola rama. Sin embargo, Git permite el uso de ramas (branches), una funcionalidad clave para gestionar proyectos de manera eficiente.

- ¿Qué es una rama en Git?

Una rama es una copia independiente de la rama principal, con su propio historial de commits. Esto permite a los desarrolladores trabajar en nuevas funciones o corregir errores sin afectar el código original. Si los cambios son útiles, se pueden fusionar con la rama principal (main o master).

¿Por qué usar ramas?
  • Permiten desarrollar nuevas características sin alterar el código estable.
  • Facilitan el trabajo en equipo sin conflictos.
  • Sirven para probar cambios antes de aplicarlos al proyecto principal.
Ejemplo teórico de cómo operar con ramas

Imagina que estamos desarrollando una página web y queremos modificar el diseño CSS sin afectar la versión en producción. Para ello, podemos crear una rama llamada estilos y trabajar allí:

  1. Creas una nueva rama llamada "estilos".
  2. Te cambias de la rama "main" a la nueva rama "estilos". Allí realizas los cambios necesarios en los archivos CSS y, si te parecen correctos, los comiteas.
  3. Vuelves a la rama "main".
  4. Fusionas los cambios de la rama "estilos" en "main".

Con este flujo, protegemos el código original y podemos decidir si queremos integrar las modificaciones en la versión principal. De manera gráfica, las operaciones realizadas se pueden representar así:

Representación gráfica del flujo de ramas en Git
Comandos para operar con ramas

Para gestionar ramas en Git, utilizamos el comando git branch. Aquí tienes algunos usos comunes:

  • Crear una nueva rama:
    git branch nuevaRama
  • Eliminar una rama local:
    git branch -d nuevaRama
  • Eliminar una rama remota:
    git push origin --delete nuevaRama
  • Cambiar a otra rama:
    git checkout nuevaRama
    Tras ejecutar este comando, estarás trabajando en la rama indicada.
  • Fusionar ramas:

    Para fusionar la rama actual con la rama que indiquemos:

    git merge nuevaRama

    Por ejemplo, para fusionar la rama nuevaRama dentro de la rama main, podemos seguir estos pasos:

    1. Cambiar a la rama main si no estamos ya:
      git checkout main
    2. Ejecutar el comando de merge:
      git merge nuevaRama

    Fusión con commit explícito (sin fast-forward):

    Si queremos forzar la creación de un commit de merge para dejar constancia explícita en el historial, usamos la opción --no-ff con un mensaje:

    git merge --no-ff nuevaRama -m "Fusionar nuevaRama a main"

    Al utilizar el parámetro --no-ff, se crea un commit de merge. El comando git merge sin opciones no deja evidencia de que una rama haya sido fusionada, ya que no crea un commit de merge, lo que puede dificultar el seguimiento del historial en git log. Usar --no-ff permite mantener un historial más claro y visual, especialmente al trabajar con ramas de funcionalidades, ya que crea un commit explícito que indica cuándo se realizó la fusión.

  • Listar las ramas disponibles en local:
    git branch

    La rama actual aparecerá marcada con un asterisco (*).

  • Listar las ramas disponibles en Remoto:
    git branch -r #modo abreviado
    git branch --remote #modo largo
                            

    La rama actual aparecerá marcada con un asterisco (*).

  • Renombrar una rama:
    git branch -m nombre_viejo nombre_nuevo #-m viene de move
    git branch --move nombre_viejo nombre_nuevo #modo largo
                            
Ejemplo práctico: Creación y fusión de ramas

En este ejemplo, mi intención es crear un archivo style.css sobre la rama pruebas con algunos cambios estéticos. Cuando esté satisfecho con el resultado, uniré las ramas. Actualmente, me encuentro en la rama pruebas, ya que he ejecutado el comando git checkout pruebas. Esto significa que cualquier cambio que realice solo afectará a esta rama.

Es importante aclarar que en un caso real, no se hacen commits constantemente. Este es solo un ejercicio de práctica para ilustrar cómo se manejan las ramas en Git.

Voy a crear el archivo /css/estilos.css, modificaré el archivo HTML para incluir un archivo CSS externo, y luego realizaré los comandos git add y git commit que ya conocemos. Además, haré más cambios en diferentes commits para que el ejemplo sea más completo.

Ahora, vamos a complicarlo un poco. Cambiaré a la rama main con el comando git checkout main, y allí realizaré algunos cambios con sus respectivos commits.

En este ejemplo, he utilizado solo comandos que ya conocemos:

  • git add . y git commit -m "comentario" para realizar los commits.
  • git branch para comprobar en qué rama estamos.
  • git checkout rama para cambiar de rama.

La rama actual aparecerá marcada con un asterisco (*).

Por último, para fusionar las ramas estando ubicado en la rama principal, ejecutaré:

git merge pruebas -m "merge pruebas"
Fusión de ramas con git merge

En la captura anterior, podemos ver cómo el comando git merge nos informa sobre los cambios realizados en el proyecto. En este caso, la fusión se ha realizado sin conflictos. Sin embargo, los conflictos ocurren cuando el mismo archivo ha sido modificado en las mismas líneas en ambas ramas. ¿Cómo resuelve Git estos conflictos? Lo explicaremos en una futura actualización de este tutorial.

Desde un cliente gráfico de Git, las ramas quedarían representadas visualmente de la siguiente forma:

Representación gráfica de las ramas en Git

Aunque estas herramientas gráficas facilitan el trabajo y ofrecen una vista más intuitiva del repositorio, tener una base sólida en Git por línea de comandos es muy útil para comprender su funcionamiento, tener un mayor control de lo que está pasando y, también, permite su uso por terminal en servidores y entornos remotos.

Trabajar con un repositorio de GitHub

Existen muchos escenarios en los que necesitaremos obtener o sincronizar un repositorio de GitHub:

  • Para colaborar en un proyecto de desarrollo: Donde varios desarrolladores tienen acceso al código y pueden contribuir con cambios.
  • Para desplegar localmente una aplicación o sitio web: Utilizando herramientas como Maven, Gradle y otros gestores de construcción, podemos configurar rápidamente un entorno de desarrollo que nos permita ejecutar la aplicación o estudiar su código fuente.
  • Para contribuir a proyectos de código abierto: A través de forks y pull requests. En este caso, el proceso implica copiar el repositorio, modificarlo en una rama independiente y luego proponer la integración de esos cambios al proyecto original.

A continuación, se presenta una lista de situaciones comunes que seguramente encontraremos al trabajar con repositorios remotos.

Importación manual de un proyecto en Eclipse

Una forma sencilla de obtener el código fuente de un proyecto alojado en GitHub —ya sea que tengamos o no permisos sobre el repositorio original— es descargarlo directamente desde la web de GitHub.

Para importar un repositorio desde GitHub a Eclipse sin usar la consola, lo primero que debemos hacer es descargar el archivo ".zip" desde la página del repositorio en GitHub y descomprimirlo en un directorio local, el cual será el directorio principal del proyecto en Eclipse.

Importante: Este método no descarga la configuración de Git del repositorio, por lo que no podremos consultar el historial de commits ni sincronizar cambios con el repositorio original mediante nuevos pushes.

Desde Eclipse, accedemos al menú File > Import > General > Projects from Folder or Archive.

A continuación, seleccionamos el directorio raíz del proyecto explorando la unidad al pulsar el botón [Directory]

Por último, hacemos clic en el botón [Finish] y el repositorio quedará importado en el disco como si fuera un proyecto creado desde cero en Eclipse. Si revisamos el directorio raíz, veremos que se ha creado el archivo .project, lo que indica que ahora es un proyecto Eclipse.

Si realizamos una modificación y consideramos conveniente crear un nuevo repositorio, podemos subirla, pero será como un repositorio propio en nuestra cuenta de GitHub, de manera completamente independiente al repositorio original.

Clonar un repositorio de GitHub en local desde la terminal

Si tenemos permisos para acceder al repositorio o simplemente es público, una forma rápida y habitual de obtenerlo es clonándolo directamente desde la terminal.

En Windows, podemos usar Git Bash, la consola que se instala junto con Git y permite ejecutar comandos de Git cómodamente.

Lo primero que tenemos que hacer es copiar la URL del repositorio desde GitHub. Para ello, entramos en la página del repositorio, pulsamos el botón verde Code y copiamos la URL del tipo HTTPS (o SSH si tenemos configurada una clave).

Una vez copiada, abrimos Git Bash, navegamos hasta el directorio donde queremos clonar el proyecto, y escribimos el siguiente comando:

git clone https://github.com/usuario/repositorio.git

Esto descargará todo el contenido del repositorio y creará una carpeta con el mismo nombre que el proyecto. Además, a diferencia de importar desde un .zip, esta vez sí tendremos configurado el repositorio con su historial de commits y conexión al remoto, lo que nos permitirá hacer pull, push y trabajar de forma completa con Git.

Para importarlo dentro del IDE Eclipse, podemos utilizar la importación manual que vimos en el apartado anterior, accediendo al menú File > Import > General > Projects from Folder or Archive.

Sincronizar un repositorio local con GitHub desde la terminal

Cuando somos propietarios de un repositorio en GitHub o formamos parte del equipo de desarrollo con los permisos adecuados, podemos sincronizar el repositorio local con el remoto para actualizar el código, crear nuevas ramas o realizar cualquier otra operación de colaboración.

Una vez descargado el repositorio con el comando git clone https://github.com/agriarte/demoRepositorio.git:

Pedro@DESKTOP-Q4VPLSR MINGW64 /g/JAVA/SpringToolSuite/DemoRepositorioLocal
$ git clone https://github.com/agriarte/demoRepositorio.git
Cloning into 'demoRepositorio'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (4/4), done.

Para comprobar que nuestra sesión local tiene los permisos configurados correctamente, podemos ejecutar el siguiente comando desde el directorio del repositorio:

$ git push
Everything up-to-date

Si todo está en orden, veremos un mensaje como el anterior, indicando que el repositorio remoto ya está actualizado con los últimos cambios locales.

Sin embargo, si no tenemos configurado un Fine-Grained Token o una Auth App, es posible que obtengamos un error como este:

 $ git push
remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/agriarte/demoRepositorio/'

Este error indica que Git está intentando autenticarse mediante usuario y contraseña, un método que GitHub ya no permite. En este caso, será necesario configurar correctamente el método de autenticación con un token de acceso personal (PAT) para poder realizar operaciones como push o pull.

Si ya existe, un token para sincronizar con el repositorio, hacemos un copiar/pegar en la ventana de Login que aparece y ya tendremos permisos de gestión del repositorio hasta que caduque

Login GitHub

Si el token es válido, la credencial se almacena en el Administrador de credenciales de Windows y permanecerá allí mientras sea válida. Puede eliminarse en cualquier momento para revocar los privilegios.

Nota: Si seleccionamos la opción "Sign in with your browser", es posible que podamos sincronizar con el repositorio remoto desde la terminal. Esto se debe a que GitHub configura automáticamente un mecanismo de autenticación interno que puede utilizarse en este equipo, siempre que tengamos una sesión activa en www.github.com. La pantalla que aparecerá será similar a la siguiente:

Login GitHub

Sin embargo, este método no será suficiente si intentamos sincronizar desde Eclipse IDE, ya que Eclipse no admite este tipo de autenticación de forma predeterminada. En este caso, necesitaremos usar un Token de Acceso Personal (PAT) para autenticar nuestras operaciones de Git dentro del IDE.

Actualizar repositorio local con la última versión del remoto

Cuando trabajamos en equipo y necesitamos actualizar nuestra versión local con la existente en remoto nos podemos encontrar con varias escenarios que requieren diferente forma de actuar para hacer la actualizacíon.

  • 1.- Nuevo archivo en remoto que no existe en local. En este escenario no podremos hacer nuevos envíos de propios hasta que el remoto (Origin) y el local no estén sincronizados.

    Por ejemplo: en el remoto del repositorio del tutorial tengo un archivo nuevo llamado "creado_en_github.txt" que no existe en local. Si intento hacer "push" de nuevos archivos, el mensaje de error me da la pista de como proceder. Dice que haga primero un "git pull" para traer el archivo a la rama local. Lo vemos:

    Pedro@DESKTOP-Q4VPLSR MINGW64 /g/JAVA/proyectosnetbean/demoRepositorio (main)
    $ git push
    To https://github.com/agriarte/demoRepositorio.git
     ! [rejected]        main -> main (fetch first)
    error: failed to push some refs to 'https://github.com/agriarte/demoRepositorio.git'
    hint: Updates were rejected because the remote contains work that you do
    hint: not have locally. This is usually caused by another repository pushing
    hint: to the same ref. You may want to first integrate the remote changes
    hint: (e.g., 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.

    Este error viene porque github no deja actualizar la rama local si hay diferencias ajenas a nuestro repositorio local. La solución está en hacer antes git pull para ponernos al día con el remoto:

    Pedro@DESKTOP-Q4VPLSR MINGW64 /g/JAVA/proyectosnetbean/demoRepositorio (main)
    $ git pull origin main
    remote: Enumerating objects: 6, done.
    remote: Counting objects: 100% (6/6), done.
    remote: Compressing objects: 100% (3/3), done.
    remote: Total 4 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
    Unpacking objects: 100% (4/4), 1.03 KiB | 1024 bytes/s, done.
    From https://github.com/agriarte/demoRepositorio
     * branch            main       -> FETCH_HEAD
       ac2329f..60d4542  main       -> origin/main
    Updating ac2329f..60d4542
    Fast-forward
     public/creado_en_github.txt | 1 +
     1 file changed, 1 insertion(+)
     create mode 100644 public/creado_en_github.txt
  • 2.- El archivo en remoto y en local tienen diferencias, y queremos que el local quede como está en el remoto.

    Este escenario ocurre cuando dos personas modifican el mismo archivo y Git no puede hacer un merge automático. Simulemos ese caso creando diferencias en el contenido de creado_en_github.txt tanto en local como en GitHub para que tengan líneas con diferencias en ambos lados.

    Si ahora intentamos un git pull, Git nos devolverá un mensaje de error por conflictos en la fusión (merge), ya que detecta que el mismo archivo fue modificado en ambas ubicaciones y no puede decidir qué versión conservar.

    $ git pull origin main
    remote: Enumerating objects: 7, done.
    remote: Counting objects: 100% (7/7), done.
    remote: Compressing objects: 100% (3/3), done.
    remote: Total 4 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
    Unpacking objects: 100% (4/4), 1.01 KiB | 1024 bytes/s, done.
    From https://github.com/agriarte/demoRepositorio
     * branch            main       -> FETCH_HEAD
       60d4542..9488b37  main       -> origin/main
    Auto-merging public/creado_en_github.txt
    CONFLICT (content): Merge conflict in public/creado_en_github.txt
    Automatic merge failed; fix conflicts and then commit the result.

    Solución al conflicto manteniendo la versión remota:

    Para esto, usamos el comando git checkout --theirs para decirle a Git que queremos la versión remota:

    (main|MERGING)$ git checkout --theirs public/creado_en_github.txt
    Updated 1 path from the index
    
    (main|MERGING)$ git add public/creado_en_github.txt
    
    (main|MERGING)$ git commit -m "Conflicto resuelto: se mantiene la versión remota"
    [main 9f37bc7] Conflicto resuelto: se mantiene la versión remota

    Con esto, descartamos los cambios locales y dejamos el archivo exactamente como está en el repositorio remoto (GitHub).

    También existe la alternativa de mantener los cambios locales utilizando git checkout --ours, pero te dejo esa opción como ejercicio para que la explores por tu cuenta.

    Alternativa: Si no te interesa conservar los cambios locales y deseas dejar tu repositorio exactamente igual que el remoto, puedes ejecutar los siguientes comandos:

    $ git fetch origin
    $ git reset --hard origin/main
  • 3.- El archivo en remoto y en local tienen diferencias, y queremos fusionarlos manualmente

    Este escenario ocurre cuando dos personas modifican el mismo archivo, y Git no puede hacer un merge automático debido a que ambas versiones tienen cambios en las mismas líneas del archivo.

    Para simular este caso, modificamos el archivo creado_en_github.txt tanto en local como en GitHub, asegurándonos de que tengan diferencias en las mismas líneas. En el repositorio local, también debemos actualizar los cambios con los comandos git add . y git commit -m "colores" para que los cambios sean reconocidos como parte del proyecto local.

    Como era de esperar, al ejecutar git pull se devuelve un error y además el promt se modifica a (main|MERGING):

    $ git pull origin main
    remote: Enumerating objects: 7, done.
    remote: Counting objects: 100% (7/7), done.
    remote: Compressing objects: 100% (4/4), done.
    remote: Total 4 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
    Unpacking objects: 100% (4/4), 1.04 KiB | 1024 bytes/s, done.
    From https://github.com/agriarte/demoRepositorio
    * branch main -> FETCH_HEAD
    6dc3c71..7ea1fed main -> origin/main
    error: Your local changes to the following files would be overwritten by merge:
    public/creado_en_github.txt
    Please commit your changes or stash them before you merge.
    Aborting
    Updating 6dc3c71..7ea1fed

    Cuando ocurre un conflicto de fusión, Git agrega marcas especiales en el archivo conflictivo para que podamos ver ambas versiones y decidir qué cambios conservar. Para resolverlo, desde Git Bash, se abre el editor "vim", que es el editor predeterminado en muchos entornos Linux y que Git instala en Windows para que lo uses desde GitBash. Aunque es un editor poco intuitivo y amigable, tiene una gran base de usuarios, por lo que es útil estar algo familiarizado con su uso.

    En el ejemplo que he desarrollado para ilustrar este tutorial, tras introducir el comando:

    $ vim public/creado_en_github.txt

    Se abre el documento con las marcas en las líneas donde hay conflictos:

    <<<<<<< HEAD
    Azul es mi color favorito
    =======
    Mi color favorito es verde
    >>>>>>> 7ea1fedf411481c8ce8bc46749a2cd2803fc2416
    Contenido editado en Github
    otro cambio github

    La sección entre <<<<<<< HEAD y ======= representa los cambios locales.

    La sección entre ======= y >>>>>>> representa las diferencias en el lado remoto

    Ahora solo se trata de eliminar las líneas con los símbolos de conflicto (el número de ID también se elimina), dejando la línea que nos interese, ya sea la local, la remota o, incluso, una tercera opción en la que creemos una versión que combine ambas.

    Una vez guardado el archivo, los cambios ya se reflejan si lo volvemos a abrir desde vim, pero puede que aún no se vean en otros editores externos como Notepad. Además, es posible que el prompt siga mostrando (main|MERGING).

    Esto se debe a que, aunque el archivo ha sido modificado, los cambios aún no han sido confirmados. En este punto, el archivo se encuentra en el stage area (zona de preparación), pero todavía no ha sido incorporado al repositorio.

    Para completar correctamente el proceso de fusión, debemos ejecutar los siguientes comandos:

    $ git add creado_en_github.txt
    $ git commit -m "Conflicto resuelto manualmente con vim"

    Una vez hecho esto, el prompt volverá a mostrar (main) y la fusión habrá concluido con éxito.

  • 4.- Usar git stash para guardar temporalmente los cambios locales antes de hacer un git pull

    Imagina que estás trabajando en el archivo creado_en_github.txt y haces algunas modificaciones:

    Contenido editado localmente sin confirmar

    No has hecho git commit, pero necesitas hacer git pull para obtener cambios recientes del repositorio remoto.

    Si intentas hacer git pull directamente, podrías obtener errores o conflictos. Para evitar eso, puedes guardar tus cambios de forma temporal con git stash:

    $ git stash
    Saved working directory and index state WIP on main: ac2329f primer commit

    Esto guarda tus cambios en una "caja temporal" y deja tu repositorio limpio.

    Ahora puedes hacer git pull sin problemas:

    $ git pull origin main
    remote: Enumerating objects: 6, done.
    remote: Counting objects: 100% (6/6), done.
    ...
    Fast-forward
    public/creado_en_github.txt | 1 +

    Una vez que has actualizado la rama, puedes recuperar tus cambios guardados con:

    $ git stash pop
    Auto-merging public/creado_en_github.txt

    Git intenta aplicar tus cambios encima del nuevo estado actualizado. Si no hay conflictos, todo irá bien. Si los hay, los resuelves como en cualquier otro conflicto.

    En resumen, lo que hacen estos 3 comandos es:

    1. git stash → Guarda los cambios sin confirmarlos
    2. git pull origin main → Trae los últimos cambios del repositorio remoto
    3. git stash pop → Recupera y aplica tus cambios guardados

    Este método es ideal para trabajar de forma segura sin tener que hacer commits intermedios innecesarios solo para poder hacer un pull.

Clonar un repositorio de GitHub en local desde Eclipse

Una forma recomendada de trabajar con un proyecto de GitHub desde Eclipse es clonar el repositorio directamente, ya que esto conserva toda la configuración de Git, incluyendo el historial de commits, ramas y la posibilidad de sincronizar cambios con el repositorio remoto.

Para clonar un repositorio desde Eclipse, seguimos estos pasos:

  1. Abrimos Eclipse y vamos al menú File > Import.
  2. En la ventana de importación, seleccionamos Git > Projects from Git y hacemos clic en Next.

    Importar GitHub
  3. Elegimos la opción Clone URI y pulsamos Next.

    Clone URI
  4. En la siguiente pantalla, introducimos la URL del repositorio de GitHub en el campo URI. Eclipse completará automáticamente los campos restantes. Si el repositorio es público, no necesitamos usuario ni contraseña. Luego hacemos clic en Next.

    URL de GitHub
  5. Seleccionamos las ramas que deseamos clonar (por defecto suele ser main o master) y hacemos clic en Next.

    Seleccionar ramas github
  6. Elegimos el directorio local donde se guardará el repositorio clonado. Podemos usar la ubicación por defecto o elegir una personalizada. Hacemos clic en Next.

    Destino proyecto
  7. En la siguiente ventana, seleccionamos cómo deseamos importar el proyecto. Si se trata de un proyecto Java estándar con estructura Eclipse, podemos elegir Import existing Eclipse projects. Si es un proyecto sin configuración de Eclipse, seleccionamos Import as general project y después podemos convertirlo manualmente.

    Tipo de proyecto
  8. Hacemos clic en Finish para completar la importación.

    Finish

Una vez importado, Eclipse reconocerá el repositorio como un proyecto Git, permitiéndonos usar todas las funcionalidades de control de versiones desde el IDE: hacer commits, crear ramas, hacer pull o push y ver el historial de cambios.

Consejo: En Eclipse, en la parte superior derecha, tenemos un acceso directo a las vistas predeterminadas de las distintas funcionalidades del IDE. Si no aparece el botón "Git" para acceder a las ventanas comunes de trabajo con Git, podemos activarlo desde el menú: Window > Perspective > Open Perspective > Other y luego seleccionar Git.

Perspectiva Git

A partir de este momento, en el panel Project Explorer, los archivos nuevos o modificados desde el último commit aparecerán con un pequeño icono de interrogación. Esto indica que aún no han sido añadidos al control de versiones. En cambio, los archivos que ya fueron guardados en la última versión mostrarán un símbolo diferente en su icono, lo que permite identificarlos fácilmente.

projectexplorer

Para añadir archivos al local stage, hacer commits y Push debemos ir a la ventana "Git Staging" de la perspectiva "Git".

gitstaging

Para añadir archivos al control de versiones, simplemente arrastramos los que queramos desde la ventana "Unstaged Changes" hacia "Staged Changes". Esta acción es equivalente al comando git add.

Una vez tengamos los archivos en "Staged Changes", podemos realizar un commit. Para ello, escribimos un mensaje descriptivo en el campo correspondiente y pulsamos el botón Commit.

Finalmente, si queremos enviar los cambios al repositorio remoto (push), hacemos clic en el botón Push Head. Esto realiza un git push a la rama actual, justo después del último commit.

Eliminar archivos

Puede suceder que necesitemos eliminar un archivo del repositorio. Para hacerlo, primero lo borramos desde el Project Explorer. A continuación, en la ventana Git Staging, veremos que el archivo eliminado aparece en la sección Unstaged Changes, marcado con un icono de una pequeña X.

Luego, arrastramos el archivo a la caja de Staged Changes. Al realizar el commit y posteriormente hacer un push, el archivo quedará eliminado del repositorio a partir de ese commit.

Recuerda que, como mencionamos anteriormente, eliminar un archivo en un commit reciente no lo elimina de los commits anteriores; estos seguirán guardando el historial del archivo eliminado.

eliminar