Flujo de trabajo de Git Cherry-pick vs Merge

302

Suponiendo que soy el mantenedor de un repositorio, y quiero obtener cambios de un contribuyente, hay algunos flujos de trabajo posibles:

  1. cherry-pickCada uno me comprometo desde el control remoto (en orden). En este caso, git registra la confirmación como no relacionada con la rama remota.
  2. En mergela rama, agrego todos los cambios y agrego un nuevo compromiso de "conflicto" (si es necesario).
  3. I mergecada confirmación de la rama remoto individualmente (de nuevo en orden), permitiendo que los conflictos que se registran para cada confirmación, en lugar de agrupar todos juntos como una sola.
  4. Para completar, podría hacer una rebase(¿igual que la cherry-pickopción?), Sin embargo, entiendo que esto puede causar confusión para el contribuyente. Quizás eso elimina la opción 1.

En ambos casos 2 y 3, git registra el historial de ramificaciones de las confirmaciones, a diferencia de 1.

¿Cuáles son las ventajas y desventajas entre el uso de uno cherry-picko los mergemétodos descritos? Tengo entendido que el método 2 es la norma, pero creo que resolver una gran confirmación con una sola fusión de "conflicto" no es la solución más limpia.

cmcginty
fuente

Respuestas:

297

Ambos rebase (y cherry-pick) y mergetienen sus ventajas y desventajas. Argumento por mergeesto, pero vale la pena entender ambos. (Busque aquí una respuesta alternativa y bien argumentada que enumere los casos en los que rebasese prefiere).

mergese prefiere sobre cherry-picky rebasepor un par de razones.

  1. Robustez . El identificador SHA1 de un commit lo identifica no solo en sí mismo sino también en relación con todos los otros commits que lo preceden. Esto le ofrece una garantía de que el estado del repositorio en un SHA1 determinado es idéntico en todos los clones. No hay (en teoría) ninguna posibilidad de que alguien haya hecho lo que parece el mismo cambio, pero en realidad está corrompiendo o secuestrando su repositorio. Puede elegir cambios individuales y probablemente sean los mismos, pero no tiene ninguna garantía. (Como un problema secundario menor, los nuevos commits seleccionados con cereza ocuparán un espacio adicional si alguien más selecciona nuevamente en el mismo commit, ya que ambos estarán presentes en la historia incluso si sus copias de trabajo terminan siendo idénticas).
  2. Facilidad de uso . La gente tiende a entender elmerge flujo de trabajo con bastante facilidad. rebasetiende a considerarse más avanzado. Es mejor comprender ambos, pero las personas que no quieren ser expertos en el control de versiones (que en mi experiencia ha incluido a muchos colegas que son muy buenos en lo que hacen, pero que no quieren pasar el tiempo extra) tienen más facilidad. El tiempo se acaba de fusionar.

Incluso con un flujo de trabajo pesado de fusión rebaseycherry-pick aún son útiles para casos particulares:

  1. Una desventaja mergees la historia desordenada. rebaseevita que una larga serie de confirmaciones se dispersen en su historial, como lo serían si se fusionara periódicamente en los cambios de otros. De hecho, ese es su propósito principal mientras lo uso. Lo que quieres tener mucho cuidado es nuncarebase codificar lo que ha compartido con otros repositorios. Una vez que se edita una confirmación, pushalguien más podría haberse comprometido además, y el rebase causará, en el mejor de los casos, el tipo de duplicación discutida anteriormente. En el peor de los casos, puede terminar con un repositorio muy confuso y errores sutiles, le llevará mucho tiempo descubrirlo.
  2. cherry-pick es útil para probar un pequeño subconjunto de cambios de una rama de tema que básicamente ha decidido descartar, pero se dio cuenta de que hay un par de piezas útiles.

En cuanto a preferir fusionar muchos cambios sobre uno: es mucho más simple. Puede ser muy tedioso hacer fusiones de conjuntos de cambios individuales una vez que comience a tener muchos de ellos. La resolución de fusión en git (y en Mercurial, y en Bazar) es muy muy buena. No se encontrará con problemas importantes al fusionar incluso ramas largas la mayor parte del tiempo. En general, combino todo de una vez y solo si obtengo una gran cantidad de conflictos hago una copia de seguridad y vuelvo a ejecutar la fusión por partes. Incluso entonces lo hago en grandes trozos. Como un ejemplo muy real, tuve un colega que tenía 3 meses de cambios para fusionar, y obtuve unos 9000 conflictos en la base de código de línea 250000. Lo que hicimos para arreglar es fusionar el valor de un mes a la vez: los conflictos no se acumulan linealmente, y hacerlo en partes resulta en mucho menos de 9000 conflictos. Todavía era mucho trabajo, pero no tanto como tratar de hacerlo un compromiso a la vez.

cuarc
fuente
1
En realidad, en teoría, existe la posibilidad de que Mallory pueda corromper su repositorio creando commits con el mismo SHA1 pero contenido diferente, probablemente nunca sucederá en la práctica. :)
Bombe
1
Ja :) Quise decir "en teoría las probabilidades son tan bajas que puedes confiar en que no suceda", pero tienes razón en que se lee al revés.
quark
¿Qué opinas sobre "merge --squash"?
cmcginty
@Bombe Si Mallory quiere tener éxito, tendría que construir específicamente el commit original y el segundo commit con el mismo SHA1. Entonces, otra pregunta podría ser: ¿cuáles son las probabilidades de que aparezcan dos (algo) falsas confirmaciones y que no te des cuenta? ;)
João Portela
64
9000 conflictos? Renuncié a mi trabajo y me convertí en un apicultor.
Sebastian Patten
95

En mi opinión, la selección de cerezas debe reservarse para situaciones raras en las que se requiere, por ejemplo, si realizó alguna corrección directamente en la rama 'maestra' (tronco, rama de desarrollo principal) y luego se dio cuenta de que debería aplicarse también a 'mantenimiento '. Debe basar el flujo de trabajo en fusión o rebase (o "git pull --rebase").

Recuerde que la confirmación seleccionada o modificada es diferente desde el punto de vista de Git (tiene un identificador SHA-1 diferente) que el original, por lo que es diferente de la confirmación en el repositorio remoto. (Rebase generalmente puede lidiar con esto, ya que verifica la identificación del parche, es decir, los cambios, no una identificación de confirmación).

También en git puedes fusionar muchas ramas a la vez: la llamada fusión de pulpo . Tenga en cuenta que la fusión de pulpos tiene que tener éxito sin conflictos. Sin embargo, puede ser útil.

HTH

Jakub Narębski
fuente
19
+1 para el punto en que rebase / cherry-picking realmente "copia" los commits y, por lo tanto, pierde el vínculo con el commit original.
studgeek
1
Usamos cherry-pick de esta manera, exclusivamente para mover los commits para la corrección de errores (quizás características MUY PEQUEÑAS) a una rama de lanzamiento existente para preparar un parche. Las características que abarcan múltiples confirmaciones generalmente garantizan entrar en una rama de lanzamiento que se basa en el maestro.
foxxtrot
3
@foxxtrot: Otra solución es crear una rama separada para una corrección de error, basada en el commit más antiguo que exhibe este error, y combinarlo en 'maint' y en 'master' ... aunque en este caso necesita saber que dicha corrección de error se aplica a ambas ramas.
Jakub Narębski
44
@Jakub Dos comandos que son indispensables para crear y fusionar una rama de git blamecorrección de errores : encontrar la confirmación que introdujo el error y git branch --containsdeterminar dónde fusionar la rama. Descrito con más detalle en esta publicación
gcbenison
-10

Rebase y Cherry-pick es la única forma de mantener limpio el historial de confirmaciones. Evite usar la fusión y evite crear conflictos de fusión. Si está utilizando gerrit, configure un proyecto en Fusionar si es necesario y un proyecto en modo selección de cereza e inténtelo usted mismo.

Nagaraj Magadum
fuente
no está claro en absoluto cómo responde esto a la pregunta, tal vez algunos ejemplos traigan algo de luz.
Adrian Nasui
1
El hecho de que su historia se vea correcta no implica que sea más fácil de entender.
nicolimo86
La fusión es la forma habitual de tener un historial limpio. Cherry-pick and rebase se usa principalmente para situaciones en las que debe modificar el historial. Lo que significa que la fusión siempre debe ser la primera opción. Porque rebase cambió comit sha`s lo que es muy peligroso cuando trabajas con controles remotos y varias personas.
Radon8472
Este tipo aquí merece una medalla. Él sabe que continuará siendo rechazado, pero es la respuesta correcta. Prestigio.
PW Kad
Lo siento, no he visto estos comentarios hasta ahora, ¡pruébelo en su entorno de prueba antes de concluir y haga lo que funcione para usted! Tengo alrededor de 600 desarrolladores que contribuyen a múltiples sucursales de productos, no me importa lo que hagan los desarrolladores en el espacio de trabajo local, cuando se envía un cambio para la integración, debe ser capaz de desarrollar la sucursal de desarrollo o, a veces, liberar o corregir la ramificación de errores. FYI ... yo uso Gerrit.
Nagaraj Magadum