¿Cómo comprometer la refactorización en progreso?

23

Entonces, tengo este gran proyecto, que está en proceso de ser refactorizado por mí. Estoy cambiando muchas cosas, por lo que no hay posibilidad de que se compile pronto. Estoy viviendo en una rama especial de git que nombré cleanup(que masterfinalmente se fusionará , por supuesto).

El problema es que yo / nosotros tenemos la política de nunca comprometer el código que no compila (idealmente también debería funcionar, pero debe compilar y vincular, como mínimo). Entonces, hasta que termine con esta gran tarea, no puedo comprometer nada (para revisión o para contabilidad).
Esta no es la forma en que me gusta trabajar (creo que la mayoría de las personas se comprometen al menos una vez al día más o menos).

¿Qué piensas? ¿Hay una solución que estoy pasando por alto?
¿Puedo decirle a git que agregue commits o algo más tarde? Podría vivir con commit sin compilación mientras permanezcan en la cleanuprama.

Editar

Sobre el tema de empujar / comprometerse: Soy consciente de que es una gran diferencia, pero más tarde, habrá revisiones rotas, cuando fusione mis cosas master. Entonces, si navega por el historial (o git bisect...), entonces las revisiones "locales" serán accesibles al mundo. Entonces, comprometerse localmente y no presionar no es la mejor solución, ya que le causará problemas más adelante (cuando el tema se cierra y se olvida por algún tiempo).

En resumen: las confirmaciones locales se impulsarán eventualmente. El historial global no debe mostrar confirmaciones que no compilan.

máscara de bits
fuente
1
Puede recopilar múltiples confirmaciones locales en una única confirmación global.
@ Thorbjørn, ¿es la recomendación de Jim a continuación, o un mecanismo diferente dentro de Git?
Brian
Creo que sí, no puedo recordar el comando exacto.
55
No estás refactorizando, estás haciendo algo más grande. Después de cada refactor en una base de código, su código debe compilarse y tener exactamente el mismo comportamiento observable. Es posible que desee cambiar el título de su pregunta para reflejar que, como mi reacción inmediata fue "Compromete lo que tienes cuando sea, todo debería funcionar".
David Thornley
1
@bitmask ¿Qué tal una reescritura?
Dave Hillier

Respuestas:

21

El git merge --squashcomando le permite crear una única confirmación encima de la rama actual cuyo efecto es el mismo que fusionar otra rama. El comando actualiza el árbol de trabajo y organiza los cambios en el índice, por lo que todo lo que debe hacer a continuación es confirmar:

git checkout master
git merge --squash cleanup
git commit -m "Merge cleanup branch"

El git rebase -icomando también puede aplastar las confirmaciones pero requiere más trabajo.

Jim Huang
fuente
14

Una reescritura no es una refactorización

Me doy cuenta de que estás interesado en cómo usar Git, pero diría que deberías considerar cambiar la forma en que realizas las refactorizaciones más que la forma en que usas Git (aunque creo que Git puede ayudarte).

Martin Fowler define la refactorización como :

Una técnica disciplinada para reestructurar un cuerpo de código existente, alterando su estructura interna sin cambiar su comportamiento externo.

Su corazón es una serie de pequeños comportamientos que preservan las transformaciones. Cada transformación (llamada "refactorización") hace poco, pero una secuencia de transformaciones puede producir una reestructuración significativa. Como cada refactorización es pequeña, es menos probable que salga mal. El sistema se mantiene funcionando completamente después de cada pequeña refactorización, lo que reduce las posibilidades de que un sistema pueda romperse gravemente durante la reestructuración.

Si aplica este método, puede comprometerse (y presionar) de forma regular.

Podría argumentar que esto no es práctico y que no funciona para algo a gran escala. Aquí es donde el método Mikado puede ayudar. Se descompone una refactorización grande en una serie de refactorizaciones pequeñas creando un gráfico de dependencia. El método es recursivo, intente hacer su cambio, no interrumpe nada, instálelo, de lo contrario, revierta su cambio y tome nota de los requisitos previos. Uno por uno, arregla esas refactorizaciones de requisitos previos hasta que pueda lograr su objetivo principal de refactorización.

Git realmente puede ayudar a este método. Puede mantener su sucursal local (rota). A medida que compromete (y empuje) los objetivos secundarios, puede rebaseramificar su objetivo principal por encima de los compromisos que acaba de hacer, hasta que ya no se rompa.

Dave Hillier
fuente
5

Consulte la página del manual para git rebase, particularmente la git rebase -ivariante. Le permite reordenar, eliminar o aplastar cualquier cantidad de confirmaciones en su historial, lo que suena como lo que está buscando. Lo uso todo el tiempo exactamente en la situación que usted describe: hacer muchos pequeños compromisos que no son adecuados para el consumo público, luego juntarlos en un solo compromiso de "refactorización" antes de pasar al repositorio compartido.


fuente
3

Estás utilizando Git, por lo que comprometerse no necesariamente implica impulsar tus cambios ...

En mi humilde opinión, y trabajando con Git, es perfectamente bueno comprometer tu trabajo, incluso si no se compila ... porque, después de todo, una vez que confirmes tus cambios, nadie tendrá el código disponible (hasta que lo presiones). Por supuesto, antes de presionarlo, debe asegurarse de que funcione bien y compilar, para que otros puedan buscar y combinar sus cambios sin ningún problema.

Además, está trabajando en una rama diferente a la principal. Entonces, si lo desea (y lo recomiendo), nunca empujará su rama. Una vez que haya terminado la refactorización, simplemente finalice la compra de la rama maestra, combine sus cambios y presione la rama maestra.

Editar

En ese caso puedes usar git cherry-picko jugar congit rebase

Cristian
fuente
Una nota importante, pero lo consideré. Por favor vea mi edición. Gracias.
bitmask
Vea mi edición arriba.
Cristian
Yo -1 si pudiera; ¡los commits estarán disponibles! Los compromisos locales de trabajo en progreso son excelentes, pero nunca los presionen; hace que el código sea más difícil de entender, interrumpe git bisect y complica la historia. Rebase o aplasta en su lugar.
RJFalconer