Integrar sangría y cambios de contenido en Git durante la fusión: ¿Mejores prácticas?

Estoy usando Git para rastrear algunos códigos de matlab. Un ejemplo de juguete ilustra mejor el problema. El proyecto hasta ahora se ve así.

C / A-- \ B 

El contenido de A es x=5

Hacemos commit C, donde la línea se cambia a x=6

Luego hacemos commit B, donde nuestro contenido es el siguiente

 if flag==1 x=5 end 

Si intentamos fusionarnos con el objective del proyecto, parece que

  C / \ A-- D \ / B 

con el resultado de fusión en D, obtendremos un conflicto, porque la línea principal ha sido cambiada en ambos (sangría añadida en B, 5 cambiada a 6 en C).

¿Existe una forma de mejores prácticas para integrar los cambios de sangrado de una sucursal y los cambios de contenido de otra sucursal para get un resultado de la fusión?

He leído acerca de una estrategia en http://sofes.miximages.com/a/5262473/288545 , y aunque eso evitaría el conflicto, descartaría la sangría a favor del cambio de contenido (lo cual es una mejora, pero aún así hace por más difícil de leer el código).

Supongo que podría aspirar y no cambiar la sangría al escribir mi código. Esto lo hace less legible, pero no es un gran problema en matlab. Sin embargo, en Python, la sangría realmente importa, entonces, ¿cómo se las arreglan python? Esto se vuelve mucho más feo si hay bloques grandes de código que luego cambiamos para estar dentro de las estructuras de control, por lo que el diff toca muchas líneas y hace que fusionar conflictos sea un gran dolor de cabeza.

¿Existe una estrategia de fusión que maneje los cambios de espacio y los cambios de contenido por separado, y luego los integre? Me gustaría que el resultado de la fusión sea

 if flag==1 x=6 end 

La key para resolver su problema es tratar las limpiezas de espacios en blanco y las reescrituras de funciones como confirmaciones separadas.

Como alguien que hace un montón de integración de sucursales, honestamente puedo decir que las dos cosas más molestas para los integradores son: 1) Codificadores a los que les gusta reformatear files que no escribieron o funciones que no reescribieron, y 2) IDEs que reformatean files completos simplemente abriéndolos y guardándolos. Claro que los files son más legibles en ambos casos, pero anula por completo el punto de control de la versión: los compromisos deben ser inteligentemente clasificados, construidos y revisados. Su order debe tener un significado. El fregadero de cocina se compromete a hacer historia inútil, y la historia no debería ser más que útil.

Esta filosofía implica "No volcar los cambios de espacio en blanco en los compromisos a los que no pertenecen". Si está reescribiendo la function tocada, claro, mejore el espaciado. De lo contrario, deje su propia confirmación y asegúrese de que los demás que trabajen en ese file sepan que se avecinan cambios en el espacio en blanco. Eso te ahorrará molestias en el momento de la integración.

Además, puede evitar errores accidentales en el espacio en blanco (espacios al final, tabs tras espacios, etc.) con el enlace pre-commit de stock de git. Emita este command en su repository para configurarlo:

 mv .git/hooks/pre-commit.sample .git/hooks/pre-commit 

Más o less emite git diff --check , que también es increíblemente útil para detectar este tipo de problemas.

Algunas herramientas de diff son mejores que otras. Yo uso KDiff3 , y lo tengo configurado para ser invocado automáticamente usando git mergetool . Todavía no es perfecto, pero a menudo puede detectar combinaciones del tipo que describes y producir automáticamente una combinación sensata.