En esta página

Git: commits, ramas y flujos de trabajo

Git es un sistema de control de versiones: guarda el historial de un proyecto para que puedas volver atrás, comparar cambios y trabajar con otras personas sin pisarse. No es una carpeta en la nube ni un botón de "guardar": es una base de datos de estados del proyecto.

Este documento va de menos a más. Primero, qué es un commit y qué es una rama (los dos conceptos sin los cuales nada de lo demás se entiende). Después, cómo usarlos. Al final, dos formas de organizar el trabajo en equipo: GitHub Flow y Git Flow.

El modelo mental

directorio de trabajo   →   staging area   →   repositorio   →   remoto
   (tus archivos)           (git add)        (git commit)      (git push)
LugarQué hay
directorio de trabajolos archivos tal como los ves y editas
staging area (índice)lo que va a entrar en el próximo commit
repositorio localel historial de commits, en .git/
remotola copia en GitHub, GitLab o el servidor que uses, para compartir y respaldar

Cuando guardas un archivo con Ctrl+S, pisas la versión anterior. Git hace lo contrario: agrega un estado nuevo al historial y deja el anterior intacto. Eso es lo que permite volver atrás.

Qué es un commit

Un commit es una foto del proyecto completo en un momento dado, con una etiqueta que la identifica. No guarda "solo las líneas que cambiaron": guarda el estado de todos los archivos que estaban en el staging area, más los datos de quién lo hizo y cuándo.

Cada commit contiene:

DatoPara qué sirve
snapshotel contenido de los archivos en ese momento
autor y fechasaber quién hizo el cambio y cuándo
mensajeexplicar por qué se hizo
hash (por ejemplo a1b2c3d)un identificador único para nombrarlo
commit padreel commit anterior, que forma una cadena

Pensalo como guardar la partida de un videojuego: no modificas la partida anterior, creas una nueva. Si algo sale mal, cargas la anterior.

Los commits se encadenan. La rama en la que estás apunta al último commit, y ese commit apunta a su padre. HEAD es el nombre que Git le da a "el commit donde estás parado ahora".

Por qué te conviene commitear

VentajaQué te resuelve
Volver atrássi rompiste algo, recuperas un estado que funcionaba
Entender el pasadogit log y git diff muestran qué cambió y cuándo
Probar sin miedopuedes experimentar sabiendo que hay una red de seguridad
Trabajar en paralelootras personas pueden partir del mismo historial
Respaldarel remoto guarda una copia fuera de tu máquina
Revisarun cambio chico se lee y se discute mucho mejor que uno gigante

La regla práctica: commitea seguido y en pasos con sentido. Un commit que mezcla "arreglo el login", "cambio el color del botón" y "actualizo la documentación" no se puede revertir sin arrastrar lo demás.

Qué es una rama

Una rama es un nombre que apunta a un commit. Nada más. No es una copia de la carpeta ni un proyecto paralelo: es una etiqueta móvil que dice "esta línea de trabajo va por aquí".

main      A ── B ── C
                    \
feature             D ── E
  • main apunta a C.
  • feature apunta a E.
  • Las dos ramas comparten los commits A, B y C.

Cuando haces un commit estando en feature, el puntero feature avanza al commit nuevo. main se queda donde estaba. Por eso crear una rama es instantáneo: solo se crea un nombre nuevo.

Un merge es unir dos líneas de trabajo: traer los commits de una rama a la otra y crear un commit que las conecta (o reubicar los commits, si se usa rebase).

Por qué te conviene usar ramas

VentajaQué te resuelve
Aislar un cambiomain sigue funcionando mientras pruebas algo
Experimentarsi la idea no sirve, borras la rama y listo
Revisar mejorel cambio completo se ve junto, separado del resto
Trabajar en paralelodos personas no se pisan en la misma línea
Revertir sin dramasi el cambio salió mal, se revierte esa rama
Ordenar el historialcada rama cuenta una historia con principio y fin

main (o master en proyectos viejos) es la rama principal: la que se supone que siempre funciona. Las demás son temporales y se borran después de integrarse.

Por qué conviene usar Git (y no solo "guardar como")

Sin GitCon Git
trabajo_final_v2_este_si.zipun historial legible de commits
no sabes qué cambió entre versionesgit diff responde en segundos
dos personas se pisan los archivosramas separadas y merges controlados
un error borra horas de trabajogit reflog recupera casi todo
no hay respaldo fuera de tu máquinael remoto guarda una copia
no puedes explicar por qué cambió algoel mensaje del commit lo explica

Git no te obliga a trabajar de una sola forma. Te da las piezas; el flujo de trabajo es el acuerdo de cómo usarlas en equipo.

Configuración inicial (una sola vez)

git config --global user.name "Tu Nombre"
git config --global user.email "tu@email.com"
git config --global init.defaultBranch main
git config --global pull.rebase false

Verificá:

git config --list

El nombre y el email quedan dentro de cada commit. Si están mal, todos tus commits muestran la identidad equivocada.

Crear o traer un repositorio

git init                    # empieza uno nuevo en la carpeta actual
git clone URL               # trae uno existente
git clone git@github.com:usuario/repo.git   # por SSH

.gitignore le dice a Git qué no trackear. Para un proyecto en C, lo mínimo:

a.out
*.o
programa
.DS_Store

Si ya commiteaste un archivo que ahora está en .gitignore, Git lo sigue trackeando. Hay que sacarlo del índice: git rm --cached archivo.

El ciclo diario

git status                  # ¿qué cambió?
git diff                    # cambios sin stage
git diff --staged           # cambios en stage
git add archivo.c           # prepara UN archivo
git add .                   # prepara todo (revisa con status antes)
git commit -m "Add main"    # guarda la foto
git log --oneline --graph   # historial resumido

git status es el comando que más vas a usar. Si alguna vez no sabes qué está pasando, empieza por ahí: te dice en qué rama estás, qué está modificado y qué está listo para commitear.

Buenos mensajes de commit

MaloMejor
cambiosFix off-by-one in pagination
arregloHandle empty input without crashing
asdAdd helper to print one character

La convención más usada: imperativo, en inglés, menos de 50 caracteres en la primera línea; si hace falta explicar, deja una línea en blanco y un párrafo.

Add guard clause for invalid sizes

Without it, negative heights make the row condition meaningless
and the loop never ends.

Ramas y merges

git switch -c feature/guard-clause   # crea y cambia
git switch main                      # vuelve a main
git branch                           # lista ramas
git merge feature/guard-clause       # trae los cambios a la rama actual
git branch -d feature/guard-clause   # borra la rama ya mergeada

git checkout todavía funciona, pero switch (ramas) y restore (archivos) son más claros y no se confunden entre sí. Usa esos.

Conflictos

Un conflicto aparece cuando dos ramas cambiaron la misma línea. Git no adivina: te deja el archivo marcado así:

<<<<<<< HEAD
    return (0);
=======
    return (1);
>>>>>>> feature/otra

Se resuelve a mano:

  1. Editas el archivo y dejas el resultado final (borras las marcas).
  2. git add archivo
  3. git commit

Regla de oro: no borres el trabajo del otro sin entenderlo. Si dudas, mira git log --merge o pregunta antes de elegir.

Remoto: subir y bajar

git remote -v                       # ¿a dónde apunta?
git remote add origin URL           # conecta un repo local con GitHub
git push -u origin main             # primera subida (crea el tracking)
git push                            # las siguientes
git fetch                           # trae novedades SIN tocar tu rama
git pull                            # fetch + merge en tu rama actual

fetch y pull no son lo mismo:

ComandoQué haceCuándo
git fetchactualiza el remoto, no toca tus archivosquieres ver antes de mezclar
git pullfetch + mergeestás seguro y quieres avanzar

Antes de elegir un flujo

Un flujo de trabajo es un acuerdo del equipo sobre cómo se usan las ramas, los commits y los remotos. No hay uno universal ni uno "correcto": depende de cómo publicas el software, cuánta gente hay y cada cuánto despliegas.

Dos aclaraciones para que los nombres no confundan:

  • Pull Request (PR) o Merge Request (MR): una propuesta para integrar una rama a otra. Muestra el diff completo, permite comentar línea por línea, ejecutar pruebas automáticas y pedir aprobación antes de mezclar.
  • Merge: la acción de integrar esa rama. La plataforma puede ofrecer distintas estrategias: merge normal (conserva los commits), squash (los aplasta en uno) o rebase (los reubica).

Git es la herramienta; GitHub, GitLab, Bitbucket y compañía son plataformas que agregan revisión y automatización encima. El flujo se puede aplicar en cualquiera.

GitHub Flow (recomendado para empezar)

Una rama por cambio, un Pull Request, y main siempre desplegable. Es el flujo más simple que sigue siendo serio: no hay ramas permanentes de más, no hay ceremonia y cualquiera puede entender dónde está cada cosa.

main ────●──────────●──────────●────►
          \        /  \        /
           ●──●──●     ●──●──●
          feature/a   feature/b

Los pasos:

  1. Actualizá main: git switch main && git pull
  2. Crea una rama con nombre descriptivo: git switch -c fix/validar-entrada
  3. Commitea en pasos chicos, cada uno con sentido propio.
  4. Sube la rama: git push -u origin fix/validar-entrada
  5. Abre un Pull Request en la plataforma que uses y pide revisión.
  6. Fusiona cuando esté aprobado y las pruebas pasen. Borra la rama.

Por qué funciona tan bien:

VentajaQué te resuelve
Un solo lugar establemain siempre se puede desplegar
Cambios chicosse revisan rápido y se revierten fácil
Revisión antes de integrarel error se detecta antes de llegar a producción
Historia legiblecada PR cuenta un cambio con su contexto
Poco protocolono hay que memorizar cinco tipos de rama

Reglas que hacen que funcione:

ReglaPor qué
main siempre funcionacualquiera puede desplegar en cualquier momento
ramas cortas (horas o días, no semanas)menos conflictos y revisiones más fáciles
un PR = un cambiose revisa mejor y se puede revertir solo
el PR explica el por quéel código ya muestra el qué
pruebas verdes antes de mergearno se discute, se verifica

Con GitHub CLI (gh) los últimos pasos son más rápidos:

gh pr create --fill        # abre el PR con los datos del commit
gh pr checks               # estado de las pruebas
gh pr merge --squash       # mergea aplastando los commits

Git Flow (para releases versionados)

Tiene más ramas y más ceremonia. Se usa cuando publicas versiones (v1.2.0) y necesitas congelar una versión mientras sigues desarrollando. La diferencia con GitHub Flow es que aquí develop es la rama de integración y main queda reservada a lo que ya está en producción.

RamaPara quéSale deVuelve a
mainsolo código en producción——
developintegración del próximo releasemainmain
feature/*una funcionalidaddevelopdevelop
release/*estabilizar una versióndevelopmain y develop
hotfix/*arreglo urgente en producciónmainmain y develop

Qué significa cada una en la práctica:

  • develop: donde se junta todo lo que va a salir en la próxima versión. No se despliega directamente.
  • feature/*: una funcionalidad o un arreglo que todavía no está listo. Sale de develop y vuelve a develop.
  • release/*: una rama para estabilizar la versión que viene. Ahí solo se corrigen errores, no se agregan funciones nuevas.
  • hotfix/*: un arreglo urgente sobre lo que ya está en producción. Sale de main y vuelve a main y a develop, para que el arreglo no se pierda en la próxima versión.
main     ──●──────────────●─────────●──►
            \            /         /
release      ●──●──●────●         /
              \                 /
develop    ────●──●──●──●──●───●────►
                \    /
feature          ●──●

Cuándo usarlo:

  • Producto con versiones y soporte de varias a la vez.
  • Equipo grande con QA y fechas de release.
  • Necesitas un hotfix sin arrastrar lo que está a medio hacer.

Cuándo no usarlo:

  • Proyectos personales, prototipos o apps que despliegas varias veces por día.
  • Equipos chicos: el costo de coordinar cinco tipos de rama supera el beneficio.

Comparación rápida

GitHub FlowGit Flow
Ramas permanentesmainmain + develop
Complejidadbajamedia/alta
Frecuencia de deploycontinuapor releases
Ideal paraweb, apps, equipos chicosproductos versionados
Riesgo principalPRs gigantesramas que viven meses

Empieza con GitHub Flow. Si algún día necesitas versiones con soporte, agregas Git Flow sin tirar nada de lo aprendido.

Deshacer sin romper nada

Esto es lo que más miedo da y lo que menos debería. La clave: distinguir si el commit ya lo viste solo tú o ya está publicado.

Quiero…Comando¿Seguro en remoto?
descartar cambios de un archivogit restore archivosí (no toca historia)
sacar algo del staginggit restore --staged archivosí
corregir el último commitgit commit --amendno si ya lo pusheaste
deshacer el último commit, dejando cambiosgit reset --soft HEAD~1solo local
deshacer el último commit y los cambiosgit reset --hard HEAD~1no: borra trabajo
revertir un commit publicadogit revert SHAsí: crea un commit nuevo
recuperar algo "perdido"git reflogsí: es tu red de seguridad

git reflog guarda todo movimiento de HEAD, incluso después de un reset --hard. Mientras no hayas hecho gc, casi siempre se puede volver.

Guardar trabajo a medias

git stash          # guarda cambios sin commitear y limpia el directorio
git stash list     # ver la pila
git stash pop      # recupera y borra de la pila
git stash apply    # recupera sin borrar

Útil cuando tienes que cambiar de rama de urgencia. No es un sustituto de los commits: si el trabajo importa, commitealo en una rama.

Etiquetas y releases

git tag -a v1.0.0 -m "Primera versión"
git push origin v1.0.0

Una etiqueta marca un commit con un nombre legible. Es lo que usa Git Flow para saber qué versión está en producción.

Errores frecuentes

Mensaje / síntomaCausaSolución
not a git repositoryestás fuera de la carpeta del repocd al repo
nothing to commitno hay cambios, o no hiciste addgit status
non-fast-forward al pushearel remoto tiene commits que no tienesgit pull y vuelve a pushear
detached HEADmiraste un commit viejo sin ramagit switch - o git switch main
Your branch is behindte falta traer cambiosgit pull
conflicto en git pullmismas líneas tocadasresuelve, add, commit
commiteaste un secretoquedó en la historiarota la clave; no alcanza con borrar el archivo
Permission denied (publickey)SSH mal configuradover SSH
borraste trabajo con reset --hardno hay papeleragit reflog y vuelve al commit

Flujo mínimo para empezar

git init
git add .
git commit -m "Add initial project structure"
git remote add origin git@github.com:laura/mi-proyecto.git
git push -u origin main

Y a partir de ahí, por cada cambio:

git switch -c feature/validar-entrada
# trabajas, compilas, pruebas
git add .
git commit -m "Validate input before processing"
git push -u origin feature/validar-entrada
# abres el PR, revisas, mergeas

Ese ciclo —rama, commits chicos, push, PR, merge— es GitHub Flow. Si el equipo usa otra plataforma, cambia el nombre del botón, no el concepto.

Siguiente parada: SSH sin miedo.


Hecho con amor para Laura, por Bogdan.