Skip to article frontmatterSkip to article content

Git Avanzado

Dominio completo del control de versiones.

¿Por qué aprender Git avanzado?

Esta guía asume que ya manejás los conceptos fundamentales de Git (de la guía básica) y podés trabajar cómodamente con comandos esenciales del día a día. Ahora es momento de subir el nivel y aprender las técnicas que usan los desarrolladores senior para gestionar proyectos complejos, colaborar eficientemente en equipos grandes, y resolver problemas sofisticados de control de versiones.

Lo que vas a aprender

Conceptos avanzados fundamentales

Antes de sumergirnos en técnicas específicas, es crucial entender algunos conceptos avanzados que aparecerán constantemente.

Referencias en Git

Git usa un sistema de referencias para identificar commits, ramas, y otros objetos. Entender estas referencias es fundamental para el trabajo avanzado.

Tipos de referencias

# Referencias absolutas
git show 1a2b3c4d5e6f                    # Hash completo del commit
git show 1a2b3c4                         # Hash corto (mínimo 4 caracteres)

# Referencias simbólicas
git show HEAD                            # Último commit de la rama actual
git show HEAD~1                          # Primer padre del HEAD
git show HEAD~3                          # Tres commits atrás
git show HEAD^                           # Primer padre (igual que HEAD~1)
git show HEAD^2                          # Segundo padre (en merges)

# Referencias de ramas
git show main                            # Último commit de la rama main
git show origin/main                     # Último commit conocido del remoto
git show feature/nueva-funcionalidad     # Último commit de la rama feature

# Referencias de tiempo
git show main@{yesterday}                # main como estaba ayer
git show main@{2.weeks.ago}              # main hace 2 semanas
git show HEAD@{5}                        # HEAD hace 5 cambios en reflog

Objetos internos de Git

Git almacena todo como objetos inmutables. Entender estos objetos te ayuda a comprender cómo funciona Git internamente.

Los cuatro tipos de objetos

# 1. Blob - contenido de archivos
git cat-file -t 1a2b3c4d    # muestra el tipo: "blob"
git cat-file -p 1a2b3c4d    # muestra el contenido

# 2. Tree - estructura de directorios
git ls-tree HEAD             # muestra el árbol del commit HEAD
git ls-tree -r HEAD          # recursivo, todos los archivos

# 3. Commit - instantánea del proyecto
git cat-file -p HEAD         # muestra la estructura del commit
# Incluye: tree, parent(s), author, committer, message

# 4. Tag - referencia a otros objetos
git show-ref --tags          # listar todos los tags
git cat-file -p v1.0.0       # información del tag

Índice y staging avanzado

El índice de Git es más poderoso que un simple “área de preparación”. Entender sus capacidades avanzadas te permite workflows más sofisticados.

# Agregar cambios parciales (hunk por hunk)
git add -p archivo.txt              # modo patch interactivo
git add -i                          # modo interactivo completo

# Trabajar con el índice directamente
git ls-files --stage                # ver contenido del índice
git diff --cached                   # diferencias entre índice y HEAD
git diff HEAD                       # diferencias entre working tree y HEAD

# Manipulación avanzada del staging
git reset HEAD~1 --soft             # mover HEAD, mantener índice
git reset HEAD~1 --mixed            # mover HEAD, resetear índice (default)
git reset HEAD~1 --hard             # mover HEAD, resetear todo

# Stash avanzado
git stash push -m "trabajo parcial" archivo.txt    # stash de archivo específico
git stash push --keep-index         # stash excepto lo que está en staging
git stash push --include-untracked  # incluir archivos untracked

Branching y estrategias de ramificación

Las ramas son la funcionalidad más poderosa de Git. Dominar el branching te permite trabajar en múltiples features simultáneamente, experimentar sin riesgo, y colaborar eficientemente.

Conceptos fundamentales de branching

# Crear y cambiar ramas
git branch feature/nueva-funcionalidad         # crear rama
git checkout feature/nueva-funcionalidad       # cambiar a rama
git checkout -b feature/otra-funcionalidad     # crear y cambiar en un comando
git switch feature/nueva-funcionalidad         # alternativa moderna a checkout

# Información de ramas
git branch                                     # listar ramas locales
git branch -r                                  # listar ramas remotas
git branch -a                                  # listar todas las ramas
git branch -v                                  # con información de últimos commits
git branch --merged                            # ramas ya fusionadas
git branch --no-merged                         # ramas pendientes de fusionar

# Configuración de tracking
git branch -u origin/feature                   # establecer upstream
git branch --set-upstream-to=origin/feature    # sintaxis alternativa
git push -u origin feature                     # push y establecer upstream

Estrategias de merge

Git ofrece múltiples estrategias para fusionar ramas, cada una apropiada para diferentes escenarios.

Fast-forward merge

# Cuando no hay commits en la rama target después del branch point
git checkout main
git merge feature/simple-change

# El historial queda lineal:
# A - B - C (main) - D - E (feature)
#                    ↑ main después del merge

Three-way merge

# Cuando ambas ramas tienen commits nuevos
git checkout main
git merge feature/complex-change

# Se crea un merge commit:
# A - B - C - F (main)
#     \     /
#      D - E (feature)

Merge strategies específicas

# Forzar merge commit incluso en fast-forward
git merge --no-ff feature/branch

# Merge solo si es fast-forward (fallar si no lo es)
git merge --ff-only feature/branch

# Estrategias de merge para casos complejos
git merge -X ours feature/branch              # preferir "nuestra" versión en conflictos
git merge -X theirs feature/branch            # preferir "su" versión en conflictos
git merge -s ours feature/branch              # ignorar completamente los cambios de la otra rama
git merge -s subtree feature/branch           # para proyectos con subárboles

Rebase: Reescribiendo la historia

git rebase es una herramienta poderosa para mantener un historial limpio y lineal. Sin embargo, requiere cuidado porque reescribe la historia.

Rebase básico vs merge

# Situación inicial:
# A - B - C (main)
#     \
#      D - E (feature)

# Con merge:
git checkout main
git merge feature
# Resultado: A - B - C - F (main)
#                \     /
#                 D - E

# Con rebase:
git checkout feature
git rebase main
git checkout main
git merge feature  # fast-forward
# Resultado: A - B - C - D' - E' (main, feature)

Rebase interactivo

El rebase interactivo te permite editar, reordenar, combinar o eliminar commits.

# Rebase interactivo de los últimos 3 commits
git rebase -i HEAD~3

# En el editor se abre algo así:
# pick 1a2b3c4 Add feature X
# pick 5d6e7f8 Fix bug in feature X
# pick 9g0h1i2 Update documentation
#
# Comandos disponibles:
# pick = usar el commit tal como está
# reword = usar el commit pero editar el mensaje
# edit = usar el commit pero parar para hacer amends
# squash = fusionar este commit con el anterior
# fixup = como squash pero descartar el mensaje de este commit
# drop = eliminar el commit

Casos de uso avanzados de rebase

# Rebase sobre otra rama
git rebase upstream/main                    # rebase sobre upstream
git rebase main feature                     # rebase feature sobre main

# Rebase con rango específico
git rebase --onto main feature~3 feature   # rebase últimos 3 commits de feature sobre main

# Rebase preservando merges
git rebase --preserve-merges main           # mantener estructura de merge commits

# Rebase con estrategia específica
git rebase -X theirs main                   # en conflictos, preferir la otra rama

# Continuar/abortar rebase
git rebase --continue                       # continuar después de resolver conflictos
git rebase --abort                         # cancelar rebase y volver al estado original
git rebase --skip                          # saltar el commit actual

Resolución avanzada de conflictos

Los conflictos son inevitables en el desarrollo colaborativo. Saber resolverlos eficientemente es una habilidad esencial.

Anatomía de un conflicto

# Cuando Git no puede fusionar automáticamente, marca los conflictos:
<<<<<<< HEAD
Código de la rama actual (HEAD)
=======
Código de la rama que se está fusionando
>>>>>>> feature/nueva-funcionalidad

Herramientas para resolución de conflictos

# Ver el estado de conflictos
git status                              # archivos en conflicto
git diff                               # ver diferencias con marcas de conflicto
git diff --name-only --diff-filter=U  # solo nombres de archivos en conflicto

# Herramientas de merge
git mergetool                          # abrir herramienta gráfica configurada
git mergetool --tool=vimdiff          # usar herramienta específica
git mergetool --tool=meld             # usar Meld (Linux)
git mergetool --tool=opendiff         # usar FileMerge (macOS)

# Configurar herramienta de merge por defecto
git config --global merge.tool vimdiff
git config --global merge.tool vscode  # VS Code

Estrategias avanzadas de resolución

# Ver diferentes versiones del archivo
git show :1:archivo.txt               # versión base (common ancestor)
git show :2:archivo.txt               # versión de HEAD (nuestra)
git show :3:archivo.txt               # versión de la rama que se fusiona (su)

# Checkout de versiones específicas
git checkout --ours archivo.txt       # usar nuestra versión
git checkout --theirs archivo.txt     # usar su versión

# Resolver conflictos en masa
git checkout --ours .                 # usar nuestra versión para todos
git checkout --theirs .               # usar su versión para todos

# Reset específico después de merge fallido
git merge --abort                     # cancelar merge y volver al estado anterior
git reset --hard HEAD                 # descartar todos los cambios

Git Workflows para equipos

Los workflows definen cómo los equipos usan Git para colaborar eficientemente. Elegir el workflow correcto es crucial para la productividad del equipo.

Git Flow

Git Flow es un workflow que define roles específicos para diferentes tipos de ramas.

# Ramas permanentes
main (master)     # código de producción, siempre estable
develop           # rama de integración, próxima release

# Ramas temporales
feature/*         # nuevas funcionalidades
release/*         # preparación de releases
hotfix/*          # fixes urgentes para producción

# Inicializar Git Flow en un repositorio
git flow init

# Trabajar con features
git flow feature start nueva-funcionalidad
git flow feature finish nueva-funcionalidad

# Trabajar con releases
git flow release start 1.2.0
git flow release finish 1.2.0

# Trabajar con hotfixes
git flow hotfix start fix-critico
git flow hotfix finish fix-critico

GitHub Flow

GitHub Flow es más simple que Git Flow, ideal para proyectos con deploy continuo.

# 1. Crear rama para nueva feature
git checkout main
git pull origin main
git checkout -b feature/nueva-funcionalidad

# 2. Hacer commits en la rama feature
git add .
git commit -m "Implementar nueva funcionalidad"
git push origin feature/nueva-funcionalidad

# 3. Crear Pull Request en GitHub
# 4. Discusión y review del código
# 5. Merge del Pull Request
# 6. Deploy automático desde main
# 7. Eliminar rama feature

git checkout main
git pull origin main
git branch -d feature/nueva-funcionalidad

Herramientas avanzadas de Git

Git Bisect: Búsqueda binaria de bugs

# Iniciar bisect
git bisect start
git bisect bad                    # commit actual tiene el bug
git bisect good HEAD~10           # commit de hace 10 era bueno

# Git automáticamente checkoutea el punto medio
# Probar si el bug está presente
git bisect bad                    # si el bug está presente
git bisect good                   # si el bug NO está presente

# Finalizar bisect
git bisect reset                  # volver al HEAD original

# Bisect automatizado con script
git bisect start HEAD HEAD~10
git bisect run pytest test_que_falla.py    # ejecutar test automáticamente

Git Reflog: Recuperar trabajo perdido

# Ver reflog
git reflog                        # reflog de HEAD
git reflog show main              # reflog de rama específica

# Recuperar commits "perdidos"
git reflog
# encuentra el SHA del commit perdido: a1b2c3d
git checkout a1b2c3d
git checkout -b recuperar-trabajo

# Recuperar después de reset accidental
git reset --hard HEAD~3           # "perdemos" 3 commits
git reflog                        # encontrar SHA anterior
git reset --hard HEAD@{1}        # volver al estado anterior

Ejercicios prácticos avanzados

Recursos para continuar aprendiendo

Documentación oficial avanzada

Herramientas avanzadas

Workflows y metodologías

Dominar Git avanzado te convierte en un desarrollador más eficiente y confiable. Las técnicas que aprendiste en esta guía son las mismas que usan equipos de desarrollo en empresas como Google, Facebook, y GitHub.

El control de versiones avanzado no es solo sobre comandos técnicos - es sobre metodologías que permiten a equipos grandes trabajar eficientemente, mantener calidad del código, y entregar software confiable.

Con estas habilidades, estás preparado para contribuir a proyectos open source complejos, liderar equipos de desarrollo, y diseñar workflows que escalen con el crecimiento de tu organización.

$ git log --oneline --graph --all
* a1b2c3d (HEAD -> main) docs: complete advanced Git guide
* 4d5e6f7 feat: add advanced workflows and automation
* 8g9h0i1 feat: add branching strategies and merge techniques
* 2m3n4o5 feat: add debugging and recovery techniques
* 6p7q8r9 init: create advanced Git guide structure

“La maestría en Git no se mide por cuántos comandos conocés, sino por qué tan elegantemente podés resolver problemas complejos de colaboración.”