División del progreso de codificación en confirmaciones significativas sin demasiada sobrecarga

23

Cuando trabajo en una solución o una característica, a veces me tropiezo con otros pequeños problemas que se pueden mejorar sobre la marcha en cuestión de segundos. Cuando los hago de inmediato y luego confirmo la función / corrección finalizada, la confirmación incluye más de una cosa. Por ejemplo "add feature X and code clean up"o "fix bug X and improved logging". Sería mejor dividir esto en dos commits. En caso de que los dos cambios ocurrieran en el mismo archivo, no puedo simplemente agregar un archivo, confirmar, agregar el otro y luego confirmar nuevamente. Entonces veo las siguientes tres opciones:

  1. Pase por alto deliberadamente cosas no relacionadas mientras trabaja en algo.

  2. Copie el archivo con dos cambios, revertirlo, incluir un cambio, confirmar, incluir el otro cambio, confirmar nuevamente.

  3. No cambie cosas pequeñas no relacionadas, agréguelas a una lista de tareas pendientes y hágalo más tarde.

Realmente no me gustan las tres opciones, debido a las siguientes razones:

  1. La calidad del código puede sufrir si uno no soluciona pequeños problemas. Y me siento mal si conscientemente pierdo la oportunidad de mejorar algo sin mucho esfuerzo.

  2. Esto aumenta el trabajo manual y es propenso a errores.

  3. Esto está bien para todos no tan pequeños, pero agregar un pequeño elemento a una lista de tareas pendientes y volver a visitarlo más tarde a menudo lleva mucho más tiempo que simplemente solucionarlo de inmediato.

¿Cómo manejas esas situaciones?

Tobias Hermann
fuente
77
¿Git no le permite verificar líneas individuales en lugar de archivos completos?
Kilian Foth
Uso git add -pmucho, lo que me permite seleccionar interactivamente las partes de los archivos que quiero comprometer. Si la limpieza está suficientemente separada, esto es fácil de hacer. Si la separación es más difícil, confirmo el estado en una rama temporal, luego agrego manualmente los cambios a mi rama real hasta que no haya diferencias en la rama temporal. Esto requiere mucho más trabajo, pero me permite verificar que cada commit funcione por sí solo.
amon
1
@gnat: obviamente no es un tonto. OP no está preguntando sobre el tamaño correcto de una confirmación: quiere hacer pequeñas confirmaciones. Es solo por buscar una forma más eficiente de hacer esto.
Doc Brown
2
@gnat: la respuesta superior no dice nada (!) sobre cómo manejar los diferentes cambios en un archivo y cómo dividirlos en confirmaciones separadas.
Doc Brown

Respuestas:

11

Creo que tienes que ser muy pragmático al programar. Incluso si fuera posible formular el esquema, el flujo de trabajo o la implementación perfectos, a veces solo necesita hacer el trabajo. Esto es lo que hago:

Utilizo la capacidad de git para organizar / comprometer trozos y líneas individuales, siempre que sea posible, para separar cambios no relacionados, aunque, ocasionalmente, esto puede introducir problemas temporales, si la separación no se realizó correctamente. Dado que los cambios serán adyacentes, generalmente no es un problema masivo, a menos que tenga una política de probar cada cambio individual en su tubería de CI.

Cuando el cambio no relacionado es demasiado grande, lo pondré en una lista de tareas pendientes y, por lo general, lo tomaré inmediatamente después, mientras esté fresco en mi mente. A veces puede tomar un día o dos antes de que pueda volver a hacerlo, depende de mi tarea actual y tren de pensamiento. Ocasionalmente, simplemente pondré un TODO: junto al código ofensivo, si no tengo una buena solución lista.

Sucede que simplemente no es práctico separar las cosas y cometeré el ajuste menor junto con el trabajo original.

El tamaño del cambio suele ser el factor determinante cuando elijo la ruta a seguir, pero al final preferiría ignorar una regla de flujo de trabajo, que dejar un olor atrás.

axl
fuente
7

Mi editor tiene un complemento que hace que la organización de partes individuales de un archivo sea extremadamente fácil. Me imagino que otros editores de programadores pueden tener complementos similares, aunque siempre puedes hacerlo de forma manual git add --patch | -p. Luego uso git stash para guardar mis otros cambios para probar mi pequeño commit de forma aislada. Luego, después de comprometerme, solo hago un git stash popy continúo donde lo dejé. Para eso precisamente fueron diseñadas esas características.

Karl Bielefeldt
fuente
2

El truco es no hacer cambios a menos que esté preparado para poner tanto esfuerzo como el cambio lo merece.

Lo que tiendo a hacer es agregar a una lista de tareas pendientes (a veces agregando comentarios al código, a veces en una nota en un ticket de error, y otras actualizando el código en una rama separada sabiendo que la solución se fusionará eventualmente). Si no hay un boleto de error para una acumulación de problemas menores de calidad, planteo uno específicamente para esto, para que yo y todos los demás podamos saber cuál fue la razón de esos cambios de código cuando se fusionó la rama. Nunca hago cambios solo por diversión, todo tiene trazabilidad para que mis colegas no se sorprendan demasiado cuando cambia el código.

En resumen, sí, pasarlos por alto al codificar. Si está agregando una función, no se sienta tentado a agregar 2 funciones, sin importar cuán pequeñas sean. Si alguien decide revertir su sucursal (porque su función ya no es necesaria, por ejemplo), entonces también perderá todas sus mini-correcciones de errores. Del mismo modo, no desea hacer una pequeña 'corrección' en algún código crítico que funcionaba correctamente.

gbjbaanb
fuente
1
El OP no sugirió fusionar dos cambios en una confirmación, sino todo lo contrario.
Doc Brown
1
Sin embargo, @DocBrown sugiere mezclar 2 cambios en una sola rama, lo que puede ser complicado de eliminar más adelante, aunque obviamente no es tan complicado como 2 cambios en una sola confirmación.
gbjbaanb
Ok, veo lo que tienes en mente con tu párrafo final.
Doc Brown
2

Una opción que uso bastante es agregar TODOcomentarios, luego hacer muchas confirmaciones "parciales" frecuentes, usando git add --patchpara seleccionar las partes relevantes del archivo. Luego, use git rebase --interactivepara reordenar y fusionar las confirmaciones parciales en la característica final y las confirmaciones de reparación antes de impulsarlas.

Esto mantiene limpio su compromiso principal y aún le permite solucionar otros problemas que encuentre de inmediato.

No hay nada malo con un git rebaseen este contexto, ya que solo está reescribiendo confirmaciones locales.

Tom
fuente
1

Otra opción podría ser "guardar" sus cambios actuales. El flujo de trabajo se vería así:

  1. Comience a hacer cambios relacionados con la Característica A
  2. Descubre el error B y decide solucionarlo de inmediato
  3. Desde la línea de comando en su repositorio realice git stash (Después de lo cual su código volverá al estado en que estaba antes de comenzar a trabajar en la Función A )
  4. En este punto, los cambios no confirmados para la función A se almacenan en el "alijo"
  5. Realice los cambios de código necesarios para corregir el error B y realice una confirmación de nuevo en el repositorio
  6. Desde la línea de comando ejecutar git stash pop
  7. Sus cambios no confirmados para la Función A ahora se eliminan del alijo y se restauran a su código en progreso junto con la corrección (ya confirmada) para el Error B
Zach
fuente
¿Podría ampliar un poco más sobre cómo funcionaría este flujo de trabajo? ¿Cuál es el estado del repositorio en cada punto? ¿Podrías guiar a alguien a través del proceso de usar git stash?
0

Separe por etapas (y confirme) los cambios relacionados con la corrección de errores. En Git Extensions, esto es extremadamente fácil de hacer. Desde la línea de comandos, creo que debes hacerlo git add -p.

Andrew Coleson
fuente