Por qué todo desarrollador necesita dominar Git
Casi todos los programadores han vivido alguna versión de esta escena: una carpeta llena de archivos llamados proyecto_final.zip, proyecto_final_v2.zip y proyecto_final_ahora_si.zip, o un cambio que rompe una aplicación que funcionaba perfectamente ayer sin que nadie sepa qué se modificó. Los sistemas de control de versiones existen precisamente para acabar con ese caos, y Git es, con mucha diferencia, el más utilizado del mundo.
Git registra cada cambio que haces en tu código, quién lo hizo y por qué. Te permite volver a cualquier estado anterior, experimentar en paralelo sin poner en riesgo la versión estable y combinar el trabajo de varias personas sobre los mismos archivos. GitHub, por su parte, es la plataforma donde millones de equipos y proyectos de código abierto alojan sus repositorios, revisan cambios y colaboran.
En este artículo vamos a construir una base sólida desde cero. Veremos qué es el control de versiones y qué tipos existen, en qué se diferencian Git y GitHub, cómo instalar y configurar Git, cuáles son los comandos esenciales del día a día, cómo trabajar con ramas y repositorios remotos, y cómo colaborar mediante pull requests. Terminaremos con los errores más frecuentes y las buenas prácticas que conviene adoptar desde el primer día.
Los ejemplos funcionan con las versiones actuales de Git, cuya rama estable más reciente es la 2.55, aunque la gran mayoría de los comandos son válidos en cualquier versión moderna.
Qué es un sistema de control de versiones
Un sistema de control de versiones es una herramienta que registra los cambios realizados en un conjunto de archivos a lo largo del tiempo. Cada vez que guardas una versión, el sistema almacena una instantánea del proyecto que puedes recuperar más adelante, comparar con otras o usar como punto de partida para nuevos cambios.
Aunque se asocia sobre todo al código, el concepto sirve para cualquier contenido basado en texto: documentación, configuraciones de infraestructura, artículos escritos en Markdown o incluso libros. A lo largo de la historia han existido tres grandes enfoques.
Los sistemas locales guardan el historial en el propio equipo del usuario. Son sencillos, pero no permiten colaborar y, si el disco falla, se pierde todo.
Los sistemas centralizados, como Subversion, almacenan el historial en un servidor único al que se conectan todos los miembros del equipo. Facilitan la colaboración y el control de acceso, pero tienen un punto único de fallo: si el servidor cae, nadie puede guardar versiones, y si se pierde sin copia de seguridad, desaparece el historial completo.
Los sistemas distribuidos, como Git o Mercurial, dan a cada desarrollador una copia completa del repositorio, con todo su historial. Se puede trabajar sin conexión, crear versiones localmente y sincronizarlas después. Cada copia funciona además como una copia de seguridad del proyecto. Este modelo es el estándar actual de la industria.
Git y GitHub: dos cosas distintas
Una confusión muy habitual entre quienes empiezan es pensar que Git y GitHub son lo mismo. No lo son, y entender la diferencia es fundamental.
Git es el sistema de control de versiones en sí. Es software libre y de código abierto, creado originalmente para gestionar el desarrollo del núcleo de Linux, y funciona por completo en tu equipo. Puedes usar Git durante años sin conectarte nunca a internet.
GitHub es un servicio web que aloja repositorios de Git y añade, alrededor de ellos, herramientas de colaboración: revisión de código mediante pull requests, seguimiento de incidencias, automatización con GitHub Actions, gestión de proyectos, wikis, publicación de paquetes y sitios web estáticos, entre muchas otras. Pertenece a Microsoft y es la plataforma más popular de su tipo.
GitHub no es la única opción. GitLab y Bitbucket ofrecen servicios similares, y también existen alternativas autoalojadas como Gitea o Forgejo. Todas ellas trabajan con repositorios de Git estándar, por lo que lo que aprendas en este artículo te servirá en cualquiera.
La relación entre ambas piezas puede resumirse así: Git gestiona el historial de tu proyecto en tu equipo, y GitHub ofrece un lugar compartido donde sincronizar ese historial con otras personas.
Instalar Git y comprobar la versión
La instalación depende de tu sistema operativo. En Windows, la opción más sencilla es el instalador oficial de Git para Windows, que incluye Git Bash, una terminal con las herramientas habituales de Unix. También puedes instalarlo con el gestor de paquetes integrado:
winget install --id Git.Git -e
En macOS, Git suele estar disponible a través de las herramientas de línea de comandos de Xcode, aunque es recomendable instalar una versión más reciente con Homebrew:
brew install git
En Linux, se instala con el gestor de paquetes de tu distribución:
# Debian y Ubuntu
sudo apt update && sudo apt install git
# Fedora
sudo dnf install git
# Arch Linux
sudo pacman -S git
Una vez instalado, comprueba que funciona:
git --version
git version 2.55.0
Las distribuciones Linux con ciclos de lanzamiento largos suelen incluir versiones de Git algo más antiguas. Para los comandos de este artículo no supone ningún problema, pero si necesitas las funciones más recientes, conviene usar los repositorios oficiales del proyecto o compilar desde el código fuente.
Configurar Git por primera vez
Antes de crear tu primer commit, Git necesita saber quién eres. Cada versión que guardes llevará asociados tu nombre y tu correo electrónico, así que conviene configurarlos de forma global:
git config --global user.name "Laura Méndez"
git config --global user.email "[email protected]"
Si vas a publicar tu trabajo en GitHub y no quieres exponer tu correo personal, la plataforma te proporciona una dirección privada del tipo [email protected] que puedes usar en su lugar.
Durante muchos años, la rama inicial de un repositorio se llamaba master. Hoy la convención extendida, y la que usa GitHub por defecto, es main. Puedes indicar a Git que use ese nombre en todos los repositorios nuevos:
git config --global init.defaultBranch main
Otras configuraciones útiles desde el primer día son elegir tu editor preferido para escribir mensajes y ajustar el comportamiento al integrar cambios remotos:
git config --global core.editor "code --wait"
git config --global pull.rebase false
Puedes revisar toda tu configuración en cualquier momento:
git config --global --list
user.name=Laura Méndez
user.email=[email protected]
init.defaultbranch=main
core.editor=code --wait
pull.rebase=false
La configuración global se guarda en el archivo .gitconfig de tu directorio personal. Si necesitas valores distintos en un proyecto concreto, como un correo de trabajo, ejecuta los mismos comandos sin --global dentro de ese repositorio.
Las tres áreas de Git
Para entender cualquier comando de Git hay que conocer primero las tres zonas por las que pasan los cambios.
El directorio de trabajo es la carpeta de tu proyecto tal como la ves en el explorador de archivos. Aquí editas, creas y borras archivos con normalidad.
El área de preparación de Git, también llamada staging o índice, es una zona intermedia donde seleccionas qué cambios formarán parte de la próxima versión. Te permite guardar solo una parte de lo que has modificado, agrupando los cambios de forma lógica.
El repositorio es la base de datos donde Git almacena de forma permanente el historial de versiones. Vive en la carpeta oculta .git en la raíz del proyecto.
recetario/
├── .git/ ← repositorio: historial completo
│ ├── HEAD
│ ├── config
│ ├── objects/
│ └── refs/
├── README.md ← directorio de trabajo
└── recetas/
└── tortilla.md
El flujo habitual es siempre el mismo: modificas archivos en el directorio de trabajo, los añades al área de preparación con git add y los guardas en el repositorio con git commit. Interiorizar este recorrido hace que el resto de comandos resulten mucho más intuitivos.
Tu primer repositorio paso a paso
Vamos a crear un pequeño proyecto para practicar los comandos básicos de Git más utilizados. Empieza creando una carpeta e inicializando un repositorio:
mkdir recetario && cd recetario
git init
Initialized empty Git repository in /home/laura/recetario/.git/
Crea un archivo y consulta el estado del repositorio con git status, el comando que más usarás:
echo "# Recetario familiar" > README.md
git status
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)
Git detecta el archivo, pero todavía no lo está siguiendo. Añádelo al área de preparación y guarda la primera versión:
git add README.md
git commit -m "Añade README con la descripción del proyecto"
[main (root-commit) 191007d] Añade README con la descripción del proyecto
1 file changed, 1 insertion(+)
create mode 100644 README.md
Cada commit recibe un identificador único, un hash del que normalmente basta con mostrar los primeros caracteres. Puedes añadir varios archivos a la vez con git add ., que prepara todos los cambios de la carpeta actual, aunque conviene revisar antes con git status qué se va a incluir.
Revisar el historial y los cambios
Una vez que tienes varios commits, Git te ofrece herramientas para entender qué ha pasado en el proyecto. El comando git log muestra el historial, y con algunas opciones se vuelve mucho más legible:
git log --oneline --graph --decorate
* a41c9e2 (HEAD -> main) Añade receta de tortilla de patatas
* 7f02b15 Crea carpeta de recetas
* 191007d Añade README con la descripción del proyecto
Para ver exactamente qué líneas has modificado antes de prepararlas, usa git diff. Si ya las has añadido al área de preparación, necesitas la opción --staged:
git diff
git diff --staged
diff --git a/recetas/tortilla.md b/recetas/tortilla.md
index 3b18e51..c4f2a90 100644
--- a/recetas/tortilla.md
+++ b/recetas/tortilla.md
@@ -3,3 +3,4 @@
- 5 huevos
- 4 patatas medianas
-- 1 cebolla
+- 1 cebolla grande
+- Aceite de oliva virgen extra
Las líneas que empiezan por - se han eliminado y las que empiezan por + se han añadido. Para inspeccionar un commit concreto, basta con git show seguido de su identificador.
Deshacer cambios con seguridad
Equivocarse forma parte del trabajo, y Git ofrece varias formas de deshacer según el punto en que te encuentres. Las versiones modernas incluyen el comando git restore, más claro que los usos antiguos de git checkout para esta tarea.
Para descartar los cambios de un archivo que todavía no has preparado:
git restore recetas/tortilla.md
Para sacar un archivo del área de preparación sin perder los cambios:
git restore --staged recetas/tortilla.md
Si acabas de hacer un commit y quieres corregir el mensaje o añadir un archivo olvidado, puedes modificar el último commit, siempre que todavía no lo hayas compartido:
git add recetas/gazpacho.md
git commit --amend -m "Añade recetas de tortilla y gazpacho"
Para deshacer un commit que ya forma parte del historial compartido, la opción segura es git revert, que crea un nuevo commit con los cambios inversos en lugar de borrar la historia:
git revert a41c9e2
Para eliminar archivos del proyecto, git rm los borra del directorio de trabajo y prepara su eliminación en el mismo paso. Con la opción --cached, Git deja de seguir el archivo pero lo conserva en tu disco, algo útil si subiste por error un archivo que debería estar ignorado.
Ignorar archivos con .gitignore
No todo lo que hay en la carpeta de un proyecto debe formar parte del repositorio. Las dependencias descargadas, los archivos compilados, los registros, las configuraciones locales del editor y, sobre todo, los archivos con credenciales deben quedarse fuera. Para ello se crea un archivo .gitignore en la raíz:
# Dependencias
node_modules/
.venv/
# Compilados y temporales
dist/
*.log
*.tmp
# Configuración local y secretos
.env
.env.local
.vscode/
.DS_Store
Git ignorará cualquier archivo o carpeta que coincida con esos patrones. Es importante crear el .gitignore al principio del proyecto, porque no afecta a los archivos que Git ya estaba siguiendo. GitHub ofrece plantillas de .gitignore para la mayoría de lenguajes y frameworks al crear un repositorio.
Ramas: trabajar en paralelo sin riesgos
Las ramas en Git son probablemente su característica más potente. Una rama es una línea de desarrollo independiente que parte de un punto del historial. Te permite trabajar en una nueva funcionalidad o en una corrección sin tocar la versión estable, y combinar el resultado cuando esté listo.
En Git, crear una rama es una operación instantánea, porque en realidad solo es un puntero a un commit. Para listar las ramas existentes:
git branch
* main
El asterisco indica la rama activa. Para crear una nueva rama y cambiarte a ella, las versiones modernas de Git ofrecen el comando git switch, pensado específicamente para este propósito:
git switch -c receta-postres
Switched to a new branch 'receta-postres'
Ahora puedes trabajar y hacer commits en esta rama sin afectar a main. Cuando termines, vuelve a la rama principal y combina los cambios con git merge:
git switch main
git merge receta-postres
Updating a41c9e2..d93b7c1
Fast-forward
recetas/flan.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 recetas/flan.md
Si main no ha cambiado desde que creaste la rama, Git simplemente avanza el puntero, lo que se conoce como fast-forward. Si ambas ramas tienen commits nuevos, Git crea un commit de fusión que une las dos historias. Una vez integrada, puedes borrar la rama con git branch -d receta-postres.
Resolver conflictos de fusión
Cuando dos ramas modifican las mismas líneas de un archivo, Git no puede decidir por sí solo qué versión conservar y marca un conflicto:
Auto-merging recetas/tortilla.md
CONFLICT (content): Merge conflict in recetas/tortilla.md
Automatic merge failed; fix conflicts and then commit the result.
El archivo afectado contiene ambas versiones, delimitadas por marcadores especiales:
## Ingredientes
<<<<<<< HEAD
- # 1 cebolla grande
- Sin cebolla
> > > > > > > receta-sin-cebolla
La parte entre <<<<<<< y ======= corresponde a tu rama actual, y la parte entre ======= y >>>>>>>, a la rama que estás integrando. Para resolverlo, edita el archivo dejando el contenido correcto, elimina los marcadores y completa la fusión:
git add recetas/tortilla.md
git commit
Los editores modernos, como Visual Studio Code, muestran los conflictos con botones para aceptar una versión, la otra o ambas, lo que simplifica mucho el proceso. Si en algún momento prefieres abandonar la fusión y volver al estado anterior, ejecuta git merge --abort.
Conectar tu proyecto con GitHub
Hasta ahora todo ha ocurrido en tu equipo. Para compartir el proyecto necesitas un repositorio remoto en GitHub donde alojarlo. Tras crear una cuenta gratuita en la plataforma, crea un repositorio nuevo desde la interfaz web, sin inicializarlo con archivos si ya tienes uno local.
Desde agosto de 2021, GitHub no admite contraseñas para operaciones de Git desde la terminal. Las dos formas recomendadas de autenticarse son las claves SSH y los tokens de acceso personal sobre HTTPS, gestionados normalmente por el administrador de credenciales del sistema.
La autenticación SSH con GitHub es la opción más cómoda a largo plazo. Genera una clave con el algoritmo Ed25519:
ssh-keygen -t ed25519 -C "[email protected]"
Añade el contenido de la clave pública, el archivo ~/.ssh/id_ed25519.pub, en la sección de claves SSH de la configuración de tu cuenta de GitHub, y comprueba la conexión:
ssh -T [email protected]
Hi lauramendez! You've successfully authenticated, but GitHub does not provide shell access.
Con la autenticación lista, vincula tu repositorio local al remoto y sube la rama principal:
git remote add origin [email protected]:lauramendez/recetario.git
git push -u origin main
La opción -u establece la relación de seguimiento entre tu rama local y la remota, de modo que en adelante bastará con escribir git push o git pull.
Una alternativa muy práctica es la herramienta oficial de línea de comandos de GitHub, que permite autenticarse y crear repositorios sin salir de la terminal:
gh auth login
gh repo create recetario --public --source=. --remote=origin --push
Clonar, sincronizar y mantenerse al día
Si el repositorio ya existe en GitHub, por ejemplo porque quieres contribuir a un proyecto o trabajar desde otro equipo, lo descargas con git clone:
git clone [email protected]:lauramendez/recetario.git
cd recetario
Este comando descarga el historial completo y configura automáticamente el remoto origin.
Cuando otras personas suben cambios, necesitas traerlos a tu copia local. El comando git fetch descarga las novedades sin modificar tus archivos, y git pull las descarga e integra en tu rama actual:
git fetch origin
git status
git pull
Your branch is behind 'origin/main' by 2 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
Un hábito saludable es hacer git pull antes de empezar a trabajar cada día, para partir siempre de la versión más reciente y reducir la probabilidad de conflictos.
Colaborar con pull requests
En GitHub, la colaboración gira en torno a las pull requests. Una pull request es una propuesta para integrar los cambios de una rama en otra, normalmente en main, que el resto del equipo puede revisar, comentar y aprobar antes de fusionarla. Dominar este flujo de trabajo con pull requests es imprescindible para trabajar en cualquier equipo moderno.
El proceso habitual es el siguiente:
- Crear una rama para el cambio a partir de
mainactualizada. - Hacer commits pequeños y descriptivos en esa rama.
- Subir la rama a GitHub con
git push. - Abrir una pull request describiendo qué cambia y por qué.
- Responder a los comentarios de la revisión y añadir los ajustes necesarios.
- Fusionar la pull request cuando se apruebe y borrar la rama.
git switch main
git pull
git switch -c corrige-tiempos-coccion
# ... editar archivos ...
git add recetas/
git commit -m "Corrige los tiempos de cocción de las recetas de horno"
git push -u origin corrige-tiempos-coccion
gh pr create --title "Corrige tiempos de cocción" --body "Ajusta los tiempos según las pruebas de la semana."
En los proyectos de código abierto en los que no tienes permisos de escritura, el flujo empieza con un fork, una copia del repositorio en tu propia cuenta. Trabajas en tu fork y abres la pull request hacia el repositorio original.
GitHub permite además proteger la rama principal para exigir revisiones aprobadas o que las pruebas automáticas de GitHub Actions pasen antes de fusionar, lo que ayuda a mantener la calidad del código en equipos de cualquier tamaño.
Errores comunes y cómo resolverlos
Al empezar con Git aparecen siempre los mismos problemas.
El primero es intentar subir cambios cuando el remoto tiene commits que no tienes en local:
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'github.com:lauramendez/recetario.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally.
La solución es integrar primero los cambios remotos con git pull, resolver los posibles conflictos y volver a hacer git push. Nunca uses git push --force en una rama compartida para saltarte este error, porque sobrescribirías el trabajo de otras personas.
El segundo es el fallo de autenticación al usar una contraseña:
remote: Support for password authentication was removed on August 13, 2021.
fatal: Authentication failed for 'https://github.com/lauramendez/recetario.git/'
Configura una clave SSH, usa gh auth login o crea un token de acceso personal.
El tercero es hacer commits en la rama equivocada. Si aún no los has subido, puedes crear una rama nueva en el punto actual y devolver la rama original a su estado anterior.
El cuarto, y más grave, es subir secretos al repositorio, como contraseñas o claves de API. Eliminarlos en un commit posterior no basta, porque siguen en el historial. Lo correcto es revocar inmediatamente la credencial expuesta, generar una nueva y, si es necesario, reescribir el historial con herramientas como git filter-repo. GitHub incluye un sistema de protección de secretos que bloquea muchos de estos envíos antes de que lleguen al repositorio.
El quinto es el estado de HEAD desacoplado, que aparece al cambiar a un commit concreto en lugar de a una rama. Si haces cambios en ese estado y quieres conservarlos, crea una rama con git switch -c nombre-rama antes de moverte a otro sitio.
Buenas prácticas desde el primer día
Adoptar algunos hábitos desde el principio hace que trabajar con Git sea mucho más agradable para ti y para tu equipo:
- Haz commits pequeños y frecuentes, cada uno con un único propósito.
- Escribe mensajes de commit claros en modo imperativo, como “Añade validación del formulario de registro”.
- Revisa siempre con
git statusygit diffantes de hacer commit. - Crea una rama para cada funcionalidad o corrección, y no trabajes directamente sobre
main. - Sincroniza a menudo con
git pullpara reducir los conflictos. - Configura el
.gitignoreal inicio y nunca subas credenciales. - Evita reescribir el historial de ramas que otras personas ya están usando.
Muchos equipos adoptan además convenciones de mensajes como Conventional Commits, que usan prefijos como feat:, fix: o docs: para clasificar los cambios y facilitar la generación automática de notas de versión:
git commit -m "feat: añade filtro de recetas por tiempo de preparación"
git commit -m "fix: corrige el cálculo de raciones en recetas escaladas"
Conclusiones
Git y GitHub son dos de las herramientas más importantes en el día a día de cualquier desarrollador. Git, un sistema de control de versiones distribuido, registra cada cambio de tu proyecto, te permite volver atrás cuando algo sale mal y hace posible experimentar en paralelo mediante ramas. GitHub, por su parte, aporta un lugar compartido para alojar los repositorios y un conjunto de herramientas de colaboración centradas en las pull requests.
El flujo esencial es sencillo una vez que se entiende: modificar archivos en el directorio de trabajo, prepararlos con git add, guardarlos con git commit y sincronizarlos con el remoto mediante git push y git pull. Sobre esa base se construye todo lo demás, desde las ramas y la resolución de conflictos hasta la revisión de código en equipo.
Las versiones actuales de Git han hecho la herramienta más amigable con comandos como git switch y git restore, y la autenticación con claves SSH o con la CLI de GitHub ha sustituido definitivamente a las contraseñas. Configurar correctamente la identidad, la rama por defecto y el .gitignore desde el principio evita muchos problemas posteriores.
Lo más importante es practicar. Crea un repositorio para tus propios proyectos, experimenta con ramas sin miedo a romper nada y contribuye a algún proyecto de código abierto mediante una pull request. Con unas semanas de uso, estos comandos se convertirán en parte natural de tu forma de trabajar.
