2009-08-06 14 views
263

suponiendo que soy el mantenedor de un acuerdo de recompra, y quiero traer cambios de un contribuyente, hay algunos flujos de trabajo posibles:Git cereza-escoge vs flujo de trabajo Combinar

  1. I cherry-pick cada una confirmación desde el mando a distancia (en orden). En este caso, git registra la confirmación como no relacionada con la rama remota.
  2. I merge rama, tirando de todos los cambios y agregando un nuevo compromiso de "conflicto" (si es necesario).
  3. I merge cada commit de la bifurcación remota individualmente (otra vez en orden), permitiendo que los conflictos sean registrados para cada commit, en lugar de agruparse todos juntos como uno solo.
  4. Para completar, puede hacer una rebase (¿igual que la opción cherry-pick?), Pero entiendo que esto puede causar confusión para el colaborador. Tal vez que elimina la opción 1.

En ambos casos 2 y 3, git registra la historia rama de las confirmaciones, a diferencia 1.

¿Cuáles son los pros y los contras entre el uso de cualquiera de cherry-pick o merge métodos descritos ? Según tengo entendido, el método 2 es la norma, pero creo que la resolución de un compromiso grande con una única combinación de "conflicto" no es la solución más limpia.

Respuesta

253

Ambos rebase (y cherry-pick) y merge tienen sus ventajas y desventajas. Argumento por merge aquí, pero vale la pena entender ambos. (Mira aquí por un suplente, bien argumentado answer casos enumerando las que se prefiere rebase.)

merge es preferible a cherry-pick y rebase por un par de razones.

  1. Robustez. El identificador SHA1 de una confirmación no solo lo identifica en sí mismo, sino también en en relación con todas las demás confirmaciones que lo preceden. Esto le ofrece una garantía de que el estado del repositorio en un SHA1 dado es idéntico en todos los clones. No existe (en teoría) ninguna posibilidad de que alguien haya hecho lo que parece ser el mismo cambio, pero en realidad está corrompiendo o secuestrando su repositorio. Puede seleccionar cuidadosamente los cambios individuales y es probable que sean los mismos, pero no tiene ninguna garantía. (Como una cuestión secundaria menor, los nuevos commits seleccionados requerirán más espacio si otra persona selecciona de nuevo el mismo commit, ya que ambos estarán presentes en el historial incluso si tus copias de trabajo son idénticas).
  2. Facilidad de uso. La gente tiende a entender el flujo de trabajo merge con bastante facilidad. rebase tiende a considerarse más avanzado. Lo mejor es entender 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 no quieren gastar el tiempo extra) tienen una tarea más fácil. tiempo de fusionarse.

Incluso con un flujo de trabajo de combinación pesado rebase y cherry-pick siguen siendo útiles para los casos particulares:

  1. Una desventaja de merge es historia desordenada.rebase evita que se esparza una larga serie de confirmaciones en su historial, como lo harían si se fusionara periódicamente en los cambios de los demás. Ese es, de hecho, su objetivo principal cuando lo uso. Lo que quiere que sea muy cuidado, nunca es rebase código que ha compartido con otros repositorios. Una vez que una confirmación es push ed, es posible que otra persona se haya comprometido a ello, y el rebase en el mejor de los casos provocará el tipo de duplicación descrita anteriormente. En el peor, puede terminar con un repositorio muy confuso y errores sutiles que le tomará mucho tiempo descubrir.
  2. cherry-pick es útil para muestrear un pequeño subconjunto de cambios de una rama temática que básicamente ha decidido descartar, pero se dio cuenta de que hay un par de piezas útiles.

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

+1

En realidad, en teoría existe la posibilidad de que Mallory corrompa su repositorio al crear confirmaciones con el mismo SHA1 pero con contenido diferente, probablemente nunca ocurra en la práctica. :) – Bombe

+1

Ha :) Quise decir "en teoría, las probabilidades son tan bajas que puedes confiar en que no va a suceder", pero tienes razón en que dice que no funciona. – quark

+0

¿Qué opinas sobre "merge --squash"? – cmcginty

84

En mi opinión, el cherry-picking debe reservarse para situaciones excepcionales donde es necesario, por ejemplo, si se arregló directamente en la rama 'master' (troncal, rama de desarrollo principal) y luego se dio cuenta de que debería aplicarse también a 'maint'. Debes basar el flujo de trabajo en merge, o en rebase (o "git pull --rebase").

Recuerde que la confirmación seleccionada o reestadificada 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 tratar con esto, ya que verifica el id del parche, es decir, los cambios, no una identificación de confirmación).

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

HTH.

+16

+1 por el hecho de que rebase/cherry-picking realmente "copia" los commits y por lo tanto pierde el enlace al commit original. – studgeek

+1

Utilizamos cherry-pick de esta manera, exclusivamente para mover confirmaciones para corregir errores (quizás características MUY PEQUEÑAS) en una rama de lanzamiento existente para preparar un parche. Las características que abarcan varias confirmaciones generalmente garantizan el acceso a una rama de publicación que está basada fuera de la maestra. – foxxtrot

+3

@foxxtrot: Otra solución es crear una rama separada para una corrección de errores, basada en la confirmación más antigua que muestre este error, y combinarla en 'maint' y en 'maestro' ... aunque en este caso necesita saber que dicho la corrección de errores se aplica a ambas ramas. –

0

Rebase y Cherry-pick es la única forma de mantener un historial de compromisos limpio. Evita usar merge y evita crear conflictos de combinación. Si está utilizando gerrit, establezca un proyecto para fusionar si es necesario y un proyecto para seleccionar el modo de selección y pruébelo usted mismo.

+0

puede elaborar un poco más. ... –

Cuestiones relacionadas