Extraiga todas las confirmaciones de una rama, envíe las confirmaciones especificadas a otra

102

Tengo las siguientes ramas:

  • master
  • production

y las siguientes ramas remotas:

  • origin/master
  • origin/production

Tengo un script que busca la origin/masterrama y obtiene la diferencia de lo que cambió desde mi última búsqueda ( log -p master..origin/master). Luego me fusiono origin/master.

Las confirmaciones encontradas se envían a una herramienta de revisión de código.

Quiero llevar las confirmaciones exitosas, y solo ellas, a la rama de producción, y luego, por supuesto, a origin/production.

¿Como lo puedo hacer?

Además, tengo 2 scripts en ejecución: el que recupera origin/master, envía los detalles de las confirmaciones a una base de datos y se fusiona, y la otra que estoy escribiendo actualmente tendrá que impulsar las confirmaciones exitosas.

Me gustaría tener esos 2 scripts ejecutándose mientras evito condiciones de carrera / conflicto de fusión. Dado que solo quiero trabajar con confirmaciones específicas, ¿tal vez haya una forma de deshacerme de las confirmaciones que no quiero?

Sylvain
fuente
¿Qué quiere decir con "confirmaciones exitosas"?
bdonlan
el que ha sido revisado y marcado como exitoso. Realmente no importa aquí, lo importante es que hay confirmaciones que quiero mantener y enviar a otra rama, y ​​otras de las que quiero deshacerme / ignorar.
Sylvain

Respuestas:

312

El término que creo que estás buscando es una 'selección de cereza'. Es decir, tome una única confirmación del medio de una rama y agréguela a otra:

A-----B------C
 \
  \
   D

se convierte en

A-----B------C
 \
  \
   D-----C'

Esto, por supuesto, se puede hacer con el comando git cherry-pick.

El problema con esta confirmación es que git considera que las confirmaciones incluyen todo el historial antes que ellas, por lo tanto, si tiene tres confirmaciones así:

A-----B-----C

Y trata de deshacerte de B, tienes que crear una confirmación completamente nueva como esta:

A-----------C'

Donde C 'tiene un ID SHA-1 diferente. Del mismo modo, seleccionar una confirmación de una rama a otra básicamente implica generar un parche, luego aplicarlo, perdiendo así el historial de esa manera también.

Este cambio de los ID de confirmación rompe la funcionalidad de fusión de git entre otras cosas (aunque si se usa con moderación, hay heurísticas que lo cubrirán). Sin embargo, lo que es más importante, ignora las dependencias funcionales: si C realmente usó una función definida en B, nunca lo sabrá.

Quizás una mejor manera de manejar esto sería tener ramas más finas. Es decir, en lugar de tener un 'maestro', tenga 'featureA', 'bugfixB', etc. Realice la revisión del código en una rama completa a la vez, donde cada rama está muy enfocada en hacer solo una cosa, y luego fusionar eso una rama cuando haya terminado. Este es el flujo de trabajo para el que está diseñado git y para lo que es bueno :)

Si insiste en lidiar con las cosas a nivel de parches, es posible que desee mirar darcs: considera que un repositorio es un conjunto de parches y, por lo tanto, la selección selectiva se convierte en la operación fundamental. Sin embargo, esto tiene su propio conjunto de problemas, como ser muy lento :)

Editar: Además, no estoy seguro de entender su segunda pregunta sobre los dos guiones. ¿Quizás podría describirlo con más detalle, posiblemente como una pregunta separada para evitar que las cosas se vuelvan confusas?

bdonlan
fuente
Acerca de mi segunda pregunta, solo quiero asegurarme de que los procesos de obtención de cambios (primer script) y empujar confirmaciones dadas a otra ubicación (segundo script) puedan funcionar sin tener una condición de carrera / conflicto de fusión, mientras se trabaja con diferentes ramas. Pero al final supongo que eso no importa ya que podría fusionar los 2 scripts en uno para que los 2 scripts no funcionen simultáneamente :)
Sylvain
9
"Este cambio de ID de confirmación rompe la funcionalidad de fusión de git, entre otras cosas" @bdonlan, por favor, explique cómo se frena la funcionalidad de fusión. Qué significa eso?
Narek
5
@Narek Probablemente quiere decir que los cambios en la confirmación C 'chocarán con los mismos cambios en la confirmación C cuando fusiones la segunda rama. Esa es la consecuencia de perder la historia detrás del commit C.
bytefu
1
"Y trata de deshacerte de B", ¿por qué estás tratando de deshacerte de B?
d512
3
@ user1334007, quiere decir que antes solía ser ABC. Ahora, debido a su selección de cereza de C, su rama es AD-C ', que ya no contiene' B '.
AnneTheAgile
1

Me doy cuenta de que esta es una pregunta antigua, pero se hace referencia aquí: Cómo fusionar una confirmación específica en Git

Por lo tanto, una respuesta más reciente: use ramas de funciones y solicitudes de extracción.

Cómo se ve esto, donde fA es una confirmación con la característica A y fB es una confirmación con la característica B:

            fA   fC (bad commit, don't merge)
           /  \ /
master ----A----B----C
                \  /
                 fB

Las solicitudes de extracción están asociadas con la funcionalidad de GitHub, pero en realidad todo lo que quiero decir es que alguien tiene la responsabilidad de fusionar las ramas de funciones en master.

MattJenko
fuente