Control de Versiones Git: La Referencia Técnica Completa para Desarrolladores
Git es un sistema de control de versiones distribuido (DVCS) que registra instantáneas del árbol de archivos de un proyecto a lo largo del tiempo, permitiendo que cualquier número de colaboradores trabajen en paralelo sin sobrescribir los cambios de los demás. Cada desarrollador tiene una copia completa del repositorio — incluyendo todo el historial de commits — en su máquina local, eliminando cualquier punto único de fallo y habilitando flujos de trabajo completamente sin conexión.
Creado por Linus Torvalds en abril de 2005 para reemplazar BitKeeper en el desarrollo del kernel de Linux, Git fue diseñado desde sus principios fundamentales en torno a tres requisitos innegociables: velocidad, integridad de datos y soporte para flujos de trabajo no lineales y distribuidos. Esos objetivos de diseño siguen definiendo lo que hace a Git categóricamente diferente de sus predecesores y por qué sigue siendo el VCS dominante más de dos décadas después.
Cómo se diferencia Git del control de versiones centralizado
Comprender la arquitectura de Git requiere una comparación directa con sistemas centralizados como Subversion (SVN) o CVS, donde un único servidor autoritativo aloja el repositorio canónico y los desarrolladores obtienen copias de trabajo superficiales.
| Dimensión | Git (Distribuido) | SVN (Centralizado) |
|---|---|---|
| — | — | — |
| Modelo de repositorio | Clon completo en cada nodo | Copia de trabajo ligera, el servidor guarda el historial |
| Capacidad sin conexión | Commit, rama, diff, log completos | Solo lectura; los commits requieren servidor |
| Coste de ramificación | Casi nulo (manipulación de punteros) | Costosa copia de directorio |
| Punto único de fallo | Ninguno — cualquier clon puede restaurar | La caída del servidor detiene todos los commits |
| Estrategia de fusión | Fusión de tres vías + rebase | Solo fusión de tres vías |
| Integridad del historial | Hash de contenido SHA-1/SHA-256 | Números de revisión secuenciales |
| Dependencia de red | Solo para push/pull/fetch | Casi todas las operaciones |
| Checkout parcial | No soportado de forma nativa | Soportado (sparse checkout) |
| Curva de aprendizaje | Curva inicial más pronunciada | Más suave para veteranos de SVN |
| Adopción (2024) | ~95% de los equipos profesionales | Entornos empresariales heredados |
El modelo distribuido significa que incluso si una plataforma de alojamiento como GitHub experimenta una interrupción, el clon local de cada desarrollador es una copia de seguridad completa y autoritativa de todo el historial del proyecto.
Arquitectura central: qué almacena realmente Git
Git no almacena diffs. Almacena instantáneas. Cada commit apunta a un objeto árbol que representa el estado completo de cada archivo rastreado en ese momento. Si un archivo no ha cambiado entre dos commits, Git almacena un puntero al blob anterior en lugar de duplicarlo — así es como Git logra tanto la completitud como la eficiencia de almacenamiento.
Los cuatro tipos de objetos fundamentales en el almacén de objetos de Git (.git/objects/) son:
- Blob — contenido de archivo sin procesar, direccionado por hash SHA
- Tree — un listado de directorio que mapea nombres de archivo a hashes de blob o subárbol
- Commit — un puntero a un árbol, cero o más commits padre, metadatos del autor y un mensaje
- Tag — un puntero anotado a un commit específico, usado para marcadores de versión
Cada objeto es inmutable y está direccionado por contenido. Cambiar un solo byte en cualquier archivo produce un hash SHA completamente diferente, que se propaga hacia arriba a través de los objetos árbol y commit. Por eso el historial de Git es criptográficamente resistente a manipulaciones — no se puede alterar silenciosamente un commit pasado sin cambiar todos los hashes de commits posteriores.
El área de preparación (también llamada índice, almacenada en .git/index) es un archivo binario que contiene el próximo commit propuesto. Este modelo de tres zonas — directorio de trabajo, índice, repositorio — es la característica arquitectónica más incomprendida de Git y la fuente de la mayor parte de la confusión de los principiantes.
Instalación y configuración de Git
Antes de ejecutar cualquier comando, verifica tu instalación y configura tu identidad. Git incorpora la información del autor en cada objeto commit, y una identidad mal configurada es una de las causas más comunes de historiales de commits desordenados en repositorios compartidos.
# Verify installation
git --version
# Set global identity (stored in ~/.gitconfig)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Set default branch name to 'main' (modern convention)
git config --global init.defaultBranch main
# Set preferred editor for commit messages
git config --global core.editor "vim"
# Enable colored output
git config --global color.ui auto
# Verify configuration
git config --listLa configuración está en capas: --system (todos los usuarios, /etc/gitconfig), --global (usuario actual, ~/.gitconfig) y --local (repositorio, .git/config). Los ámbitos más específicos anulan a los más amplios.
Comandos esenciales de Git: referencia completa
Inicialización y clonación
git init crea un nuevo repositorio escribiendo un directorio .git/ en la carpeta actual. No crea ningún commit — el repositorio comienza vacío.
git init
git init my-project # Initialize into a new subdirectory
git init --bare repo.git # Bare repository (no working tree, used for servers)Un repositorio bare contiene solo el almacén de objetos y las refs — sin directorio de trabajo. Este es el formato correcto para un repositorio remoto al que varios desarrolladores hacen push. Si estás alojando Git por tu cuenta en un servidor de VPS Hosting, inicializa siempre los repositorios compartidos como bare.
git clone crea una copia local completa de un repositorio remoto, incluyendo todas las ramas, etiquetas e historial.
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git # SSH transport (preferred for auth)
git clone --depth 1 https://github.com/user/repo.git # Shallow clone (latest commit only)
git clone --branch develop https://github.com/user/repo.git # Clone specific branchLos clones superficiales (--depth) son útiles para pipelines de CI/CD donde solo necesitas el estado más reciente, no el historial completo. Reducen drásticamente el tiempo de clonación en repositorios grandes, pero impiden algunas operaciones dependientes del historial como git bisect.
Inspección del estado
git status es el comando que se ejecuta con más frecuencia en cualquier flujo de trabajo. Muestra el estado de las tres zonas de tu repositorio.
git status
git status -s # Short format: two-column status codes
git status -sb # Short format with branch infogit diff compara contenido entre zonas o commits.
git diff # Working directory vs. index (unstaged changes)
git diff --staged # Index vs. last commit (what will be committed)
git diff HEAD # Working directory vs. last commit (all changes)
git diff main..feature # Compare tips of two branches
git diff abc123..def456 # Compare two specific commits
git diff --stat # Show changed files and line counts onlygit log recorre el grafo de commits. Sus opciones de filtrado están entre las características más potentes y menos utilizadas de Git.
git log
git log --oneline --graph --decorate --all # Visual branch graph
git log -p # Show patch (diff) for each commit
git log --author="Jane" # Filter by author
git log --since="2 weeks ago" # Filter by date
git log --grep="fix:" # Filter by commit message pattern
git log -- path/to/file # History of a specific file
git log --follow -- path/to/file # Follow renamesLa combinación --graph --oneline --decorate --all es tan universalmente útil que la mayoría de los ingenieros la crean como alias:
git config --global alias.lg "log --oneline --graph --decorate --all"Preparación y commit
git add filename.py # Stage a specific file
git add src/ # Stage an entire directory
git add . # Stage all changes in current directory
git add -p # Interactive patch staging (stage hunks, not whole files)
git add -u # Stage modifications and deletions, but not new filesLa preparación interactiva (git add -p) es una de las características más potentes y menos utilizadas de Git. Permite revisar y preparar selectivamente fragmentos individuales dentro de un archivo, habilitando commits precisos y atómicos incluso cuando el directorio de trabajo contiene múltiples cambios no relacionados.
git commit -m "feat: add OAuth2 token refresh logic"
git commit --amend # Modify the most recent commit (message or content)
git commit --amend --no-edit # Amend content without changing the message
git commit -v # Open editor showing full diff of staged changesRegla crítica: Nunca modifiques commits que ya hayan sido enviados a un remoto compartido. Modificar un commit reescribe su hash, obligando a los colaboradores a hacer rebase o reset de sus ramas locales.
Push y pull
git push origin main
git push origin feature/auth # Push a specific branch
git push -u origin feature/auth # Push and set upstream tracking
git push --force-with-lease # Safer force push (fails if remote has new commits)
git push origin --delete old-branch # Delete a remote branch
git push --tags # Push all local tagsPrefiere --force-with-lease sobre --force cuando debas reescribir el historial remoto. Comprueba que nadie más haya hecho push desde tu último fetch, evitando pérdidas accidentales de datos.
git pull origin main
git pull --rebase origin main # Fetch and rebase instead of merge
git pull --ff-only # Only fast-forward; abort if a merge commit would be createdgit fetch descarga los cambios remotos sin tocar tu directorio de trabajo ni la rama actual. Esta es la forma segura de inspeccionar los cambios del upstream antes de integrarlos.
git fetch origin
git fetch --all # Fetch from all remotes
git fetch --prune # Remove remote-tracking branches that no longer exist upstreamRamificación y fusión: el flujo de trabajo central
El modelo de ramificación de Git es su característica arquitectónicamente más significativa. Una rama es simplemente un puntero con nombre (un archivo de 41 bytes en .git/refs/heads/) a un hash de commit. Crear una rama es instantáneo independientemente del tamaño del repositorio.
Gestión de ramas
git branch # List local branches
git branch -a # List all branches (local and remote-tracking)
git branch -v # List branches with last commit info
git branch feature/user-auth # Create a new branch
git branch -d feature/user-auth # Delete merged branch
git branch -D feature/user-auth # Force delete (even if unmerged)
git branch -m old-name new-name # Rename a branchCambio de ramas
Git moderno (2.23+) separa las funciones de git checkout en dos comandos dedicados:
git switch main # Switch to existing branch
git switch -c feature/payments # Create and switch in one step
git restore filename.py # Discard working directory changes to a file
git restore --staged filename.py # Unstage a file (remove from index)git checkout sigue funcionando para todo esto, pero git switch y git restore tienen una semántica más clara y menos ambigua, y deben preferirse en flujos de trabajo modernos.
Estrategias de fusión
git merge feature/user-auth # Standard merge (creates merge commit if needed)
git merge --no-ff feature/user-auth # Always create merge commit (preserves branch topology)
git merge --squash feature/user-auth # Squash all branch commits into one staged change
git merge --abort # Abort an in-progress conflicted mergeLa fusión fast-forward ocurre cuando la rama de destino no ha divergido de la fuente — Git simplemente mueve el puntero hacia adelante. No se crea ningún commit de fusión. --no-ff fuerza un commit de fusión incluso en este caso, lo que preserva el historial visual de las ramas de características en git log --graph.
La fusión squash colapsa todos los commits de una rama de características en un único cambio preparado, que luego se confirma manualmente. Esto produce un historial lineal limpio en main pero descarta el historial de commits detallado de la rama de características.
Rebase
git rebase reproduce los commits de una rama sobre otra, reescribiendo sus hashes para crear un historial lineal.
git rebase main # Rebase current branch onto main
git rebase -i HEAD~5 # Interactive rebase: edit last 5 commits
git rebase --onto main server client # Transplant client branch onto main, excluding server
git rebase --abort # Abort a rebase in progress
git rebase --continue # Continue after resolving a conflictEl rebase interactivo (-i) es la herramienta de higiene de commits del profesional. Permite reordenar, aplastar, editar, eliminar o dividir commits antes de compartirlos. Caso de uso habitual: limpiar una rama de características desordenada antes de abrir un pull request.
| Estrategia | Historial | Caso de uso | Riesgo |
|---|---|---|---|
| — | — | — | — |
| Merge (predeterminado) | No lineal, preserva ramas | Ramas de características de larga duración | `git log` ruidoso |
| Merge `–no-ff` | No lineal, commits de fusión explícitos | Topología de ramas forzada | Igual que el anterior |
| Merge `–squash` | Lineal, un commit por característica | Rama principal limpia | Pierde el historial detallado |
| Rebase | Lineal, sin commits de fusión | Ramas personales, limpieza pre-PR | Reescribe hashes; peligroso en ramas compartidas |
| Cherry-pick | Selectivo, lineal | Retroportar correcciones | Commits duplicados entre ramas |
La regla de oro del rebase: Nunca hagas rebase de commits que existan en una rama pública y compartida. El rebase reescribe los hashes de los commits. Si un compañero ha basado trabajo en esos commits, su historial divergirá y se enfrentará a una reconciliación dolorosa.
Resolución de conflictos de fusión
Los conflictos ocurren cuando dos ramas modifican la misma región del mismo archivo. Git marca el conflicto en el archivo con marcadores de conflicto estándar:
<<<<<<< HEAD
const timeout = 30000;
=======
const timeout = 60000;
>>>>>>> feature/increase-timeoutFlujo de trabajo de resolución:
# After a conflicted merge or rebase
git status # Identify conflicted files (marked as "both modified")
# Edit each conflicted file, remove markers, keep correct content
git add resolved-file.js # Mark as resolved
git commit # Complete the merge (message is pre-populated)Para conflictos complejos, una herramienta de fusión de tres vías proporciona una vista más clara:
git mergetool # Launch configured merge tool (vimdiff, meld, etc.)
git config --global merge.tool vimdiffDeshacer cambios: la matriz de decisión
Elegir el comando de deshacer incorrecto es una de las formas más comunes en que los desarrolladores pierden trabajo o corrompen el historial compartido. La elección correcta depende de dos variables: dónde vive el cambio y si ha sido enviado.
| Escenario | Comando | Reescribe el historial | Seguro en rama compartida |
|---|---|---|---|
| — | — | — | — |
| Deshacer la preparación de un archivo | `git restore –staged file` | No | Sí |
| Descartar cambios del directorio de trabajo | `git restore file` | No | Sí |
| Deshacer el último commit, mantener cambios preparados | `git reset –soft HEAD~1` | Sí | No |
| Deshacer el último commit, mantener cambios sin preparar | `git reset HEAD~1` | Sí | No |
| Deshacer el último commit, descartar todos los cambios | `git reset –hard HEAD~1` | Sí | No |
| Deshacer un commit enviado de forma segura | `git revert <hash>` | No | Sí |
| Eliminar un archivo de todo el historial | `git filter-repo` | Sí | No |
git reset --soft HEAD~1 # Undo commit, keep changes in index
git reset HEAD~1 # Undo commit, keep changes in working dir
git reset --hard HEAD~1 # Undo commit, discard all changes permanently
git revert abc1234 # Create new commit that inverts abc1234
git revert HEAD~3..HEAD # Revert last 3 commits (creates 3 revert commits)
git revert -n HEAD~3..HEAD # Stage the reversals without committing (batch revert)git reset --hard es irreversible mediante comandos normales de Git. Si lo ejecutas accidentalmente, tu único camino de recuperación es git reflog, que registra cada posición a la que ha apuntado HEAD durante aproximadamente 90 días.
git reflog # Show HEAD movement history with hashes
git checkout -b recovery abc1234 # Recover by creating a branch at the lost commitComandos avanzados para flujos de trabajo en producción
git stash
git stash guarda el estado actual de tu directorio de trabajo e índice en una pila, dándote un árbol de trabajo limpio para cambiar de contexto.
git stash # Stash tracked changes
git stash -u # Include untracked files
git stash push -m "WIP: auth refactor" # Stash with a descriptive name
git stash list # List all stash entries
git stash pop # Apply most recent stash and remove it from stack
git stash apply stash@{2} # Apply specific stash without removing it
git stash drop stash@{2} # Delete a specific stash entry
git stash branch feature/wip # Create a new branch from a stashgit cherry-pick
git cherry-pick abc1234 # Apply a single commit to current branch
git cherry-pick abc1234 def5678 # Apply multiple commits
git cherry-pick abc1234 --no-commit # Apply changes without committing
git cherry-pick main~3..main # Apply a range of commitsCherry-pick es el mecanismo estándar para retroportar correcciones de errores a ramas de mantenimiento. Si corriges una vulnerabilidad de seguridad crítica en main, haces cherry-pick de ese commit en v2.1-stable y v2.0-stable sin fusionar características no relacionadas.
git bisect
git bisect realiza una búsqueda binaria a través del historial de commits para encontrar el commit exacto que introdujo un error. Es una de las herramientas de depuración más potentes y menos conocidas de Git.
git bisect start
git bisect bad # Mark current commit as broken
git bisect good v2.3.0 # Mark a known-good commit or tag
# Git checks out the midpoint commit automatically
# Test your code, then:
git bisect good # If this commit is fine
git bisect bad # If this commit is broken
# Repeat until Git identifies the first bad commit
git bisect reset # Return to original HEAD when doneEn un repositorio con 1.000 commits entre los puntos bueno y malo, git bisect encuentra al culpable en un máximo de 10 pasos.
git tag
Las etiquetas marcan commits específicos como significativos — típicamente versiones de lanzamiento.
git tag v1.4.2 # Lightweight tag (just a pointer)
git tag -a v1.4.2 -m "Release 1.4.2" # Annotated tag (recommended; stores metadata)
git tag -a v1.4.2 abc1234 # Tag a specific past commit
git push origin v1.4.2 # Push a specific tag
git push origin --tags # Push all tags
git tag -d v1.4.2 # Delete local tag
git push origin --delete v1.4.2 # Delete remote tagUsa siempre etiquetas anotadas para los lanzamientos. Almacenan el nombre, correo electrónico, fecha y un mensaje del etiquetador, y pueden firmarse con GPG. Las etiquetas ligeras son apropiadas solo para marcadores locales temporales.
git worktree
git worktree permite que múltiples directorios de trabajo sean extraídos del mismo repositorio simultáneamente — cada uno en una rama diferente. Esto elimina la necesidad de guardar en stash o hacer commit del trabajo en progreso cuando necesitas cambiar a una corrección urgente.
git worktree add ../hotfix-branch hotfix/critical-auth-bug
git worktree list
git worktree remove ../hotfix-branchEsto es especialmente valioso en un Servidor Dedicado que ejecuta un pipeline de CI/CD donde múltiples trabajos de compilación necesitan acceso simultáneo a diferentes ramas del mismo repositorio sin interferir entre sí.
Flujos de trabajo de Git para equipos
La estrategia de ramificación correcta depende de tu cadencia de lanzamiento y el tamaño del equipo. Existen tres modelos dominantes:
Flujo de trabajo de ramas de características
Cada característica o corrección vive en su propia rama. Los desarrolladores abren pull requests para fusionar en main. Simple y efectivo para la mayoría de los equipos.
Gitflow
Define ramas de larga duración main y develop, además de ramas de corta duración feature/, release/ y hotfix/ con reglas de fusión estrictas. Apropiado para software con lanzamientos versionados explícitos (bibliotecas, aplicaciones empaquetadas).
Desarrollo basado en trunk
Los desarrolladores hacen commit directamente en main (o usan ramas de muy corta duración fusionadas en un día). Depende en gran medida de los feature flags para ocultar el trabajo incompleto. Preferido por equipos de alta velocidad que practican el despliegue continuo.
| Flujo de trabajo | Cadencia de lanzamiento | Tamaño del equipo | Complejidad de CI/CD |
|---|---|---|---|
| — | — | — | — |
| Rama de características | Flexible | Cualquiera | Baja |
| Gitflow | Lanzamientos programados | Mediano–Grande | Media |
| Basado en trunk | Despliegue continuo | Cualquiera | Alta |
Alojamiento de repositorios Git: autoalojado vs. plataformas gestionadas
Para equipos que requieren soberanía de datos, cumplimiento normativo o infraestructura privada, alojar un servidor Git propio es una opción viable y a menudo necesaria. Las opciones incluyen Gitea (ligero, basado en Go), GitLab CE (plataforma DevOps completa) y Forgejo (fork de Gitea con gobernanza comunitaria).
Una instancia mínima de Gitea autoalojada funciona cómodamente en un plan de VPS Hosting con 2 vCPUs y 2 GB RAM. Para equipos más grandes o GitLab CE con runners de CI, 4–8 GB RAM es el mínimo práctico.
Al autoalojar, asegura tu servidor Git con:
- Autenticación por clave SSH (deshabilita completamente la autenticación por contraseña)
- HTTPS con un certificado válido — los Certificados SSL son esenciales para proteger las credenciales en tránsito
- Reglas de firewall que limiten la exposición del puerto Git (22 o puerto SSH personalizado, 443 para HTTPS)
- Copias de seguridad automatizadas regulares de los directorios de repositorio bare
.git - Secretos de webhook para integraciones de CI/CD
Para equipos que usan pipelines de despliegue basados en Git que también gestionan infraestructura web, combinar un servidor Git autoalojado con un VPS con cPanel te proporciona hooks de despliegue integrados junto con herramientas familiares de gestión de alojamiento.
Hooks de Git: automatización de puertas de calidad
Los hooks de Git son scripts que se ejecutan automáticamente en puntos específicos del ciclo de vida de Git. Viven en .git/hooks/ y no se confirman en el repositorio de forma predeterminada (usa una herramienta como pre-commit o husky para compartirlos).
Hooks clave para flujos de trabajo en producción:
| Hook | Disparador | Uso habitual |
|---|---|---|
| — | — | — |
| `pre-commit` | Antes de que se cree el commit | Ejecutar linters, formateadores, pruebas |
| `commit-msg` | Después de que se escribe el mensaje del commit | Aplicar el formato de commit convencional |
| `pre-push` | Antes del push al remoto | Ejecutar la suite de pruebas completa |
| `post-receive` | Después de que el remoto recibe un push | Disparar despliegue, enviar notificaciones |
| `pre-rebase` | Antes de que comience el rebase | Prevenir el rebase de ramas compartidas |
# Example pre-commit hook: reject commits with debug print statements
#!/bin/bash
if git diff --cached | grep -E '^+.*(console.log|debugger|print("DEBUG)'; then
echo "ERROR: Debug statement detected. Remove before committing."
exit 1
fiEl hook post-receive en un repositorio bare del servidor es la base del despliegue simple basado en Git: haces push al servidor, el hook extrae el nuevo HEAD en la raíz web, ejecuta los pasos de compilación y reinicia los servicios — sin necesidad de una plataforma CI externa.
.gitignore: mantener los repositorios limpios
El archivo .gitignore le indica a Git qué archivos y patrones dejar sin rastrear. Debe confirmarse en el repositorio y mantenerse cuidadosamente.
# Dependencies
node_modules/
vendor/
# Build artifacts
dist/
build/
*.o
*.pyc
__pycache__/
# Environment and secrets — NEVER commit these
.env
.env.local
*.pem
*.key
config/secrets.yml
# IDE files
.idea/
.vscode/
*.swp
# OS files
.DS_Store
Thumbs.dbTrampa crítica: Si un archivo ya estaba siendo rastreado antes de añadirse a .gitignore, Git continuará rastreándolo. Debes dejar de rastrearlo explícitamente:
git rm --cached path/to/sensitive-file
git commit -m "chore: stop tracking secrets file"Nunca confirmes credenciales, claves API o claves privadas en un repositorio — ni siquiera en uno privado. Usa variables de entorno, gestores de secretos (HashiCorp Vault, AWS Secrets Manager) o archivos .env que estén en .gitignore.
Ajuste de rendimiento para repositorios grandes
Git estándar se degrada en repositorios con millones de archivos o gigabytes de activos binarios. Estrategias de mitigación:
- Git LFS (Large File Storage): Reemplaza los archivos binarios grandes con archivos de puntero en el repositorio y almacena el contenido real en un servidor LFS separado. Esencial para repositorios que contienen medios, pesos de modelos de ML o binarios compilados.
- Clon parcial:
git clone --filter=blob:nonedescarga commits y árboles pero obtiene blobs bajo demanda. Reduce drásticamente el tamaño del clon inicial para monorepos grandes. - Sparse checkout:
git sparse-checkout set path/to/subdirextrae solo un subconjunto del árbol de trabajo. Útil en monorepos donde un desarrollador solo trabaja en un directorio de servicio. - Archivo commit-graph:
git commit-graph write --reachableprecalcula el grafo de commits, acelerando operaciones comogit log --graphy consultas de alcanzabilidad en historiales grandes. git maintenance start: Programa tareas de mantenimiento en segundo plano (empaquetado de objetos sueltos, actualizaciones del commit-graph, prefetch de fetch) para mantener las operaciones del repositorio rápidas con el tiempo.
Lista de verificación técnica de puntos clave
Antes de considerar tu configuración de Git lista para producción, verifica cada uno de los siguientes puntos:
- Identidad configurada:
user.nameyuser.emailconfigurados correctamente en el ámbito de configuración apropiado - Claves SSH en uso: Autenticación por contraseña a remotos reemplazada por pares de claves SSH o HTTPS basado en tokens
.gitignoreconfirmado: Secretos, artefactos de compilación y archivos del SO excluidos antes del primer commit- Rama predeterminada llamada
main:init.defaultBranchconfigurado globalmente para evitar el nombre heredadomaster - Los mensajes de commit siguen una convención: Conventional Commits (
feat:,fix:,chore:) o formato acordado por el equipo aplicado mediante el hookcommit-msg git revertpara el historial público:git reset --hardusado solo en commits locales no enviados--force-with-leaseen lugar de--force: Previene la sobreescritura accidental de los pushes de los compañeros- Etiquetas anotadas para lanzamientos:
git tag -acon un mensaje, no etiquetas ligeras - Hooks compartidos mediante
pre-commitohusky: Puertas de calidad aplicadas de forma consistente en todo el equipo - Git LFS configurado si el repositorio contiene activos binarios superiores a 1 MB
- Repositorio bare en el servidor: Remotos autoalojados inicializados con
git init --bare git fetch --pruneregular: Las refs de seguimiento remoto mantenidas sincronizadas con el estado real del remoto
Preguntas frecuentes
¿Cuál es la diferencia entre git fetch y git pull?
git fetch descarga commits, ramas y etiquetas del remoto en tus refs de seguimiento remoto locales (p. ej., origin/main) sin tocar tu directorio de trabajo ni la rama actual. git pull es git fetch seguido inmediatamente de git merge (o git rebase si está configurado). Usa git fetch cuando quieras inspeccionar los cambios del upstream antes de integrarlos.
¿Cuándo debo usar git rebase en lugar de git merge?
Usa rebase para linearizar tu rama de características local antes de abrir un pull request, manteniendo el historial del proyecto legible. Nunca hagas rebase de una rama que otros desarrolladores ya hayan clonado o en la que hayan basado trabajo — reescribir los hashes de commits publicados obliga a todos los demás a reconciliar manualmente los historiales divergentes.
¿Cómo elimino permanentemente un archivo sensible que fue confirmado accidentalmente?
Usa git filter-repo (el reemplazo moderno de git filter-branch): git filter-repo --path secrets.env --invert-paths. Esto reescribe todo el historial del repositorio, eliminando el archivo de cada commit. Después de reescribir, haz force-push de todas las ramas y etiquetas, luego rota las credenciales expuestas inmediatamente — asume que están comprometidas independientemente de la rapidez con que actúes.
¿Qué es el estado HEAD desconectado y cómo me recupero de él?
HEAD desconectado significa que tu puntero HEAD hace referencia directamente a un hash de commit específico en lugar de a un nombre de rama. Cualquier commit que hagas no pertenecerá a ninguna rama y quedará inaccesible después de que cambies. Para recuperarte: git switch -c new-branch-name para adjuntar los commits a una nueva rama, o git switch main para descartarlos.
¿Cómo maneja Git los archivos binarios de forma diferente a los archivos de texto?
Git almacena los archivos binarios como blobs opacos — no puede calcular diffs significativos a nivel de línea ni realizar fusiones automáticas en ellos. Los conflictos en archivos binarios deben resolverse eligiendo completamente una versión. Para repositorios con activos binarios significativos, configura Git LFS para almacenar los binarios externamente y mantener el repositorio en sí ligero y rápido.
