2010-06-18 12 views
16

Como la mayoría de las personas que son nuevas en Git, he tenido mi cuota de confusión tratando de descifrar los casos de uso aplicables a git merge y git rebase. Creo que finalmente he decidido que, en lo que respecta al estado de copia de trabajo resultante, te dan lo mismo. Además, ambos resultan en los mismos conflictos. Si esto es incorrecto, por favor brinde un ejemplo para iluminarme.git workflow: fusiona y git-rerere - ¿Cuál es el punto?

Desde mi punto de vista, la principal ventaja de usar rebase en lugar de combinar (si los cambios no se han realizado) es mantener el historial lineal. Lo que realmente no entiendo es el razonamiento detrás del desarrollo de git-rerere.

Desde las páginas de manual, se supone que git-rerere lo ayudará en el caso en que intente resolver un conflicto que haya resuelto previamente. El ejemplo que estoy a punto de consultar se encuentra en http://www.kernel.org/pub/software/scm/git/docs/git-rerere.html.

Si la política de su proyecto es no fusionar constantemente los cambios desde la línea principal en su rama de tema (como el núcleo de Linux), el ejemplo anterior dice que crear confusiones de fusión "desechables". Básicamente, combina el maestro en tu tema, ejecuta pruebas para asegurarte de que todo sigue funcionando, luego haz un "reinicio de git --hard HEAD ^", esencialmente descartando la fusión. Más adelante, cuando creas otro commit de merge "throw-away", git-rerere te ayuda a resolver los conflictos que ya has resuelto en la primera combinación de throw-away.

¿Alguien puede explicar por qué en lugar de pasar por todas las molestias de crear una confirmación de fusión temporal, el desarrollador no bastaría simplemente con volver a establecer su tema en el maestro? ¿No es ese el objetivo de git-rebase: obtener los cambios, pero evitar la fusión? ¿Esto no logra lo mismo y, suponiendo que nadie haya sacado los cambios de la rama temática, no sería un enfoque mucho más simple? ¿Es el flujo de trabajo throw-away-merge + git-rerere realmente solo para el caso cuando tus cambios han sido empujados/tirados?

Una última pregunta - Linus es citado diciendo "Pero si veo un montón de 'Merge branch linus' en tus registros, no voy a alejarte de ti, porque tu árbol obviamente tiene basura al azar en él eso no debería estar allí ... "¿Tendría también Linus un problema con las rebases constantes?

Respuesta

21

Tiene razón en que el rebase y la fusión pueden producir el mismo árbol final. La historia que producen es muy diferente, sin embargo, el control de versiones es, por supuesto, todo sobre la historia. Has expresado una preferencia por la historia lineal; eso es realmente deseable a escala local, mientras que las fusiones ayudan a registrar la interacción a gran escala de características, correcciones de errores, etc.

La respuesta simple a su pregunta central (¿por qué no simplemente rebase?) Es que a veces hay un lugar correcto para que se inicie una sucursal, y si ese es el caso, debe fusionar, no volver a establecer.

Por ejemplo, podría tener una corrección de error que se aplica a una versión de mantenimiento, así como la versión actual; querrá ramificarlo del último compromiso, que es un antecesor de ambos lanzamientos. No se puede volver a establecer la base de esa bifurcación a lo largo de la rama principal o de mantenimiento, o ya no sería posible fusionarla en la otra.

Del mismo modo, todas las ramas de temas comienzan en alguna parte. En algún momento, quieres preservar ese historial. Usted menciona uno de los casos bien definidos (otros han retirado su trabajo), pero podría ser algo mucho menos obvio. Tal vez haya alguna interacción con otras características, tal vez esta característica tenga subfunciones, y está tratando de mantener toda esa jerarquía preservada.

Así que, claro, si la sucursal es local y no hay motivos para mantener su base fija, es mucho más sencillo simplemente rebasarla y terminarla. Pero a veces eso no es lo correcto.

Su última pregunta es en realidad sobre algo muy diferente, nada que ver con conflictos de combinación. Linus dijo que in the context de fusiones que no era necesario hacer. Este es un problema de rama y fusión de filosofía. Junio ​​Hamano escribió un excellent blog post sobre ese mismo problema. Una breve cita que resume el tema que nos ocupa:

cuando combina una rama tema 'complemento Frotz' a tu rama 'master', que son, evidentemente, incorporando la nueva función 'Frotz', pero lo más importante, usted está indicando que es deseable tener esa característica '' Frotz en la rama 'master'

Linus no quiere ver que la fusión de esta rama extraña llamada 'Linus' todo el tiempo, porque es evidente que' re no fusionar un tema específico que es deseable tener en su rama. Está fusionando repetidamente la rama ascendente con la rama temática, que es completamente la dirección incorrecta. No necesita todo el material de master (o linus) para desarrollar su tema. ¡Deberías terminar tu tema, luego fusionarlo para el otro lado, corriente arriba en el maestro! No es deseable tener todo el contenido del maestro en su rama de tema. (Y el maestro de un único desarrollador es realmente una rama temática, en lo que concierne a un integrador).

Entonces, Linus no tiene problemas con las fusiones frecuentes; él tiene un problema con fusiones sin sentido y contraproducentes. (Y, en general, si se asegura de que sus fusiones se realicen por una buena razón, no serán frecuentes, y casi nunca se fusionarán en sentido descendente). Si sus rebases se hacen por una buena razón, y hacen la historia mejor, entonces son algo bueno, aunque frecuente.

+0

Genial, gracias por la respuesta. El comentario de corrección de errores - rama de la última confirmación que es un antepasado de ambos, en realidad fue muy esclarecedor. Parece una idea simple, pero estaba bajo la impresión de que uno debería ramificarse desde la punta de una rama de la maintentance, y luego seleccionar el arreglo de errores para el maestro.Sin embargo, este enfoque parece mucho más limpio, y evita necesariamente el rebasamiento. – Josh

+0

@ user370562: El principio aquí es fusionar hacia arriba/hacia arriba, y crear sus ramas de tal manera que eso sea posible. (Por cierto, las ramas de mantenimiento con frecuencia se pueden fusionar de nuevo con el maestro, las correcciones de errores que ha realizado en v5 probablemente todavía se apliquen a la versión en desarrollo v6.) La mayoría de las sugerencias de flujos de trabajo enfatizan la fusión hacia arriba, consulte 'man gitworkflows', por ejemplo . ¡Me alegra ser de ayuda! – Cascabel

6

¿No es esto lo mismo, y suponiendo que nadie ha sacado los cambios de rama de tema, no sería este un enfoque mucho más simple? ¿Es el flujo de trabajo throw-away-merge + git-rerere realmente solo para el caso cuando tus cambios han sido empujados/tirados?

Ha golpeado el clavo en la cabeza. Rebasar es bueno para las ramas que aún no has publicado; rerere es útil para las ramas que ha publicado (es decir, las ramas para las cuales el rebasamiento sería inapropiado/molesto para los desarrolladores indirectos).

¿Tendría también Linus un problema con las rebases constantes?

No, porque cambio de base no da lugar a la fusión comete, y, por encima, no se puede ver que una rama ha sido sincronizado, mientras que se puede ver fácilmente si una rama se ha fusionado en el otro brazo varias veces.

0

rama por flujo de trabajo recomienda que haya una rama de integración temporal. En tal escenario, si rebase, tendría que volver a establecer una base (o jalar) en una rama temporal que puede tener un checkin diferente en la versión final. Hacer tu rebase realmente inútil. O para el caso, si atrajo su rama, ese tirón puede resultar inútil.

Sin embargo, aunque ayudará mucho para aliviar el dolor de fusión recurrente.