Por qué importa el staging granular
Un historial de Git bien elaborado cuenta una historia. Cada commit representa un único cambio lógico: una corrección de bug, un refactoring, una nueva funcionalidad. Pero el desarrollo real raramente es tan ordenado. Corriges un bug, luego notas un error tipográfico cercano, luego ajustas algo de formato, luego comienzas un pequeño refactoring -- todo en el mismo archivo. Si pones en staging y haces commit del archivo entero de una vez, terminas con un commit que mezcla cambios no relacionados. Eso hace que la revisión de código sea más difícil, la búsqueda de bugs con bisect más difícil, y el historial de commits menos útil como documentación.
El staging granular te permite dividir tu trabajo en commits significativos, incluso cuando los cambios están entrelazados dentro del mismo archivo. En lugar de hacer commit de todo a la vez, eliges exactamente qué cambios van juntos.
Tres niveles de staging
Staging a nivel de archivo
El nivel más básico. Pones en staging archivos enteros con git add:
git add src/auth.ts src/utils.ts
Esto está bien cuando cada archivo contiene un solo cambio lógico. Pero tan pronto como un archivo contiene múltiples modificaciones no relacionadas, el staging a nivel de archivo es demasiado grueso.
Staging a nivel de hunk
Git puede dividir los cambios de un archivo en "hunks" -- bloques contiguos de líneas modificadas separados por código sin cambios. Usando git add -p (modo patch), Git presenta cada hunk uno a la vez y pregunta si debe ponerse en staging:
git add -p src/auth.ts
Para cada hunk, eliges y (stagar), n (saltar), s (dividir en hunks más pequeños), o e (editar manualmente). Esta es una mejora importante sobre el staging a nivel de archivo, pero tiene limitaciones. Los hunks se definen por proximidad: si dos cambios no relacionados están cerca (separados por menos de tres líneas de contexto), Git los agrupa en un solo hunk. Separarlos requiere edición manual de patches, lo cual es tedioso y propenso a errores.
Staging a nivel de línea
El staging a nivel de línea es la opción más precisa. En lugar de trabajar con archivos o hunks, seleccionas líneas individuales para poner en staging. ¿Quieres stagar las líneas 12 y 15 pero no la línea 14? Puedes hacerlo. Esto te da control completo sobre qué entra en cada commit, independientemente de lo cerca que estén los cambios en el archivo.
En la línea de comandos, el staging a nivel de línea significa editar patches manualmente con git add -p y la opción e. Necesitas entender el formato de diff unificado, modificar cuidadosamente el patch y esperar no introducir errores. Funciona, pero no es algo que la mayoría de los desarrolladores quieran hacer regularmente.
Staging a nivel de línea en GitSquid
GitSquid hace que el staging a nivel de línea sea visual y sencillo. Cuando seleccionas un archivo modificado, el visor de diff muestra cada línea cambiada. Para poner en staging líneas específicas:
- Haz clic en una sola línea para seleccionarla.
- Cmd+Click (Ctrl+Click en Windows/Linux) para seleccionar múltiples líneas individuales.
- Shift+Click para seleccionar un rango de líneas.
Una vez que hayas seleccionado las líneas que quieres, ponlas en staging. Solo esas líneas se añaden al índice. El resto permanece como modificaciones sin stagar en tu directorio de trabajo, listo para ser incluido en un commit diferente.
El mismo flujo de trabajo funciona a la inversa. Si ya has puesto en staging líneas que quieres quitar del área de staging, puedes seleccionarlas en el diff en staging y quitar solo esas líneas del staging.
Cómo funciona internamente
Cuando pones en staging líneas individuales, GitSquid genera un patch en el lado del servidor que incluye solo los cambios seleccionados. Este patch se aplica luego al índice usando el mecanismo de patches de Git. Al manejar la generación del patch en el servidor en lugar de manipular el diff en el cliente, el resultado es confiable y coincide exactamente con lo que Git espera. No hay problemas de formato ni errores de desplazamiento que podrías encontrar al editar patches a mano.
Ejemplos prácticos
Separar una corrección de bug de un refactoring
Estás trabajando en un refactoring y notas un bug. Lo corriges inmediatamente porque la solución es obvia. Ahora tu archivo tiene dos tipos de cambios: el refactoring y la corrección del bug. Con el staging a nivel de línea, seleccionas solo las líneas de la corrección del bug, las haces commit con un mensaje claro como "fix null check in auth validation", y luego haces commit del refactoring por separado. El resultado son dos commits limpios y revisables en lugar de uno confuso.
Separar código de debug de código de producción
Añadiste algunas sentencias console.log mientras depurabas, justo al lado de los cambios reales del código. En lugar de intentar recordar qué líneas son de debug y cuáles son reales, seleccionas visualmente solo los cambios de producción, los pones en staging y haces commit. Las líneas de debug permanecen en tu directorio de trabajo donde puedes seguir usándolas o descartarlas después.
Preparar un commit parcial para revisión
Tienes un gran conjunto de cambios, pero solo parte del trabajo está lista para revisión. El staging a nivel de línea te permite hacer commit de las porciones terminadas mientras mantienes el código en progreso sin commitear. Tu pull request se mantiene enfocada, y el revisor no tiene que navegar por código incompleto.
Mantener commits atómicos
Un commit atómico es aquel que contiene un único cambio lógico y completo. Pasa los tests, no rompe el build y puede entenderse por sí solo. Los commits atómicos no son solo cuestión de orden. Tienen beneficios prácticos:
- Revisión de código. Los revisores pueden entender cada commit independientemente. Un commit titulado "fix input validation" que solo toca lógica de validación es fácil de revisar. Un commit titulado "various changes" que toca validación, estilos y configuración no lo es.
- Caza de bugs. Cuando algo se rompe,
git bisectpuede señalar el commit exacto que introdujo el problema. Los commits atómicos hacen que el resultado sea significativo: encuentras el cambio específico que causó el bug, no una mezcla de modificaciones no relacionadas. - Revert. Si un commit necesita ser revertido, un commit atómico puede revertirse limpiamente. Un commit mixto podría forzarte a revertir cambios que realmente querías conservar.
- El historial como documentación. Meses después, cuando alguien lee el historial de commits para entender por qué existe un fragmento de código, los commits atómicos con mensajes claros cuentan una historia útil.
El staging a nivel de línea es la herramienta que hace que los commits atómicos sean prácticos. Sin él, crear commits limpios a partir del desarrollo real desordenado requiere disciplina y esfuerzo manual. Con él, el proceso es tan simple como seleccionar las líneas que van juntas.
Los mejores commits son los que hacen exactamente una cosa. El staging granular te da el control para lograrlo, incluso cuando tu directorio de trabajo cuenta una historia diferente.