Tengo el siguiente diseño de repositorio:
- rama maestra (producción)
 - integración
 - trabajando
 
Lo que quiero lograr es elegir una serie de confirmaciones de la rama de trabajo y fusionarla con la rama de integración. Soy bastante nuevo en git y no puedo entender cómo hacer exactamente esto (la elección de los rangos de confirmación en una operación, no la fusión) sin alterar el repositorio. ¿Alguna sugerencia o pensamiento sobre esto? ¡Gracias!
                    
                        git
                                git-merge
                                git-cherry-pick
                                
                    
                    
                        crazybyte
fuente
                
                fuente

Respuestas:
Cuando se trata de una variedad de compromisos, selección de cerezas
esNo fue práctico.Como se menciona a continuación por Keith Kim , Git 1.7.2+ introdujo la capacidad de seleccionar una variedad de confirmaciones (pero aún debe ser consciente de las consecuencias de la selección de cerezas para una futura fusión )
Damian comenta y nos advierte:
Si desea elegir el rango a
BtravésD(inclusive) , seríaB^..D.Consulte " Git create branch from range of previous commits " como ilustración.
Como Jubobs menciona en los comentarios :
Nota: a partir de Git 2.9.x / 2.10 (Q3 2016), puede elegir un rango de confirmación directamente en una rama huérfana (cabeza vacía): consulte " Cómo hacer que una rama existente sea huérfana en git ".
Respuesta original (enero de 2010)
A
rebase --ontosería mejor, donde reproduzca el rango de compromiso dado en la parte superior de su rama de integración, como Charles Bailey describió aquí .(también, busque "Aquí es cómo trasplantaría una rama de tema basada en una rama a otra" en la página de manual de git rebase , para ver un ejemplo práctico de
git rebase --onto)Si su rama actual es la integración:
Eso reproducirá todo entre:
first_SHA-1_of_working_branch_range(de ahí el~1): la primera confirmación que desea reproducirintegration" (que apunta a la última confirmación que desea reproducir, desde laworkingrama)a "
tmp" (que señala hacia dóndeintegrationapuntaba antes)Si hay algún conflicto cuando se reproduce uno de esos commits:
git rebase --continue".git rebase --skip"git rebase --abort" (y vuelva a colocar laintegrationrama en latmprama)Después de eso
rebase --onto,integrationvolverá a la última confirmación de la rama de integración (es decir "tmp" rama + todas las confirmaciones reproducidas)Con la selección de cerezas o
rebase --onto, no olvides que tiene consecuencias en las fusiones posteriores, como se describe aquí .Aquí
cherry-pickse discute una " " solución pura , e implicaría algo como:Pero de todos modos, cuando necesite "reproducir" una serie de confirmaciones, la palabra "reproducir" debería empujarlo a usar la función "
rebase" de Git.fuente
-mopción, ¿cómo maneja esos compromisos? ¿O hay una manera de filtrar estos commits?-mSe supone que @aug los manejará por usted, seleccionando la línea principal a la que hace referencia el-mparámetro que ha elegido para esta selección de cerezas.-mopción solo cuando llegue a una confirmación principal cuando se selecciona una variedad de confirmaciones? En este momento, si paso-mcomogit cherry-pick a87afaaf..asfa789 -m 1se aplica a todos los commits dentro del rango.error: Commit 8fcaf3b61823c14674c841ea88c6067dfda3af48 is a merge but no -m option was given.que en realidad se dio cuenta de que sólo pudieragit cherry-pick --continuey que estaría bien (pero no incluiría los padres se comprometan)A partir de git v1.7.2 cherry pick puede aceptar una variedad de confirmaciones:
fuente
cherry-pick A..Bno obtendrá el commit A (lo necesitaríaA~1..Bpara eso), y si hay algún conflicto, git no continuará automáticamente como lo hace rebase (al menos a partir del 1.7.3.1)git cherry-pick A..B Cno funciona como cabría esperar, ingenuamente. ¡No elegirá todo en el rangoA..By se comprometeráC! Para hacer esto, debe dividirse en dos líneas, primerogit cherry-pick A..By luegogit cherry-pick C. Por lo tanto, siempre que tenga un rango, debe ejecutarlo por separado.Suponga que tiene 2 ramas,
"branchA": incluye confirmaciones que desea copiar (de "commitA" a "commitB"
"branchB": la rama a la que desea que se transfieran los commits desde "branchA"
1)
2) obtener los ID de "commitA" y "commitB"
3)
4)
5) En caso de que tenga un conflicto, resuélvalo y escriba
para continuar el proceso de selección de cerezas.
fuente
¿Estás seguro de que no quieres fusionar las ramas? Si la rama de trabajo tiene algunas confirmaciones recientes que no desea, puede crear una nueva rama con un HEAD en el punto que desee.
Ahora, si realmente desea elegir una variedad de confirmaciones, por cualquier razón, una forma elegante de hacerlo es simplemente extraer un parche y aplicarlo a su nueva rama de integración:
Esto es esencialmente lo que git-rebase está haciendo de todos modos, pero sin la necesidad de jugar. Puede agregar
--3wayagit-amsi necesita fusionar. Asegúrese de que no haya otros archivos * .patch ya en el directorio donde hace esto, si sigue las instrucciones al pie de la letra ...fuente
A^incluidoA.Envolví código de VonC en una escritura del golpe corto,
git-multi-cherry-pickpara facilidad de movimiento:Actualmente estoy usando esto mientras reconstruyo el historial de un proyecto que tenía tanto el código de terceros como las personalizaciones mezcladas en el mismo tronco svn. Ahora estoy dividiendo el código de terceros, los módulos de terceros y las personalizaciones en sus propias ramas git para una mejor comprensión de las personalizaciones en el futuro.
git-cherry-pickEs útil en esta situación ya que tengo dos árboles en el mismo repositorio, pero sin un antepasado compartido.fuente
Todas las opciones anteriores le pedirán que resuelva los conflictos de fusión. Si está fusionando los cambios comprometidos para un equipo, es difícil resolver los conflictos de fusión de los desarrolladores y continuar. Sin embargo, "git merge" hará la fusión de una sola vez, pero no puede pasar un rango de revisiones como argumento. tenemos que usar los comandos "git diff" y "git apply" para hacer la combinación de rango de revoluciones. He observado que "git apply" fallará si el archivo de parche tiene diferencias para demasiados archivos, por lo que tenemos que crear un parche por archivo y luego aplicarlo. Tenga en cuenta que el script no podrá eliminar los archivos que se eliminan en la rama de origen. Este es un caso raro, puede eliminar manualmente dichos archivos de la rama de destino. El estado de salida de "git apply" no es cero si no puede aplicar el parche,
Debajo está el guión.
fuente
Lo probé hace unos días, después de leer la explicación muy clara de Vonc.
Mis pasos
comienzo
dev: ABCDEFGHIJtarget: ABCDEniHPasos para copiar características sin los pasos E y H en la rama
dev_feature_wo_E_Hgit checkout devgit checkout -b dev_feature_wo_E_Hgit rebase --interactive --rebase-merges --no-ff Ddonde pusedropdelanteEyHen el editor de rebasecommitPasos para copiar la rama
dev_feature_wo_E_Hen el destino.git checkout targetgit merge --no-ff --no-commit dev_feature_wo_E_HcommitAlgunas observaciones
cherry-picken los días anterioresgit cherry-pickes potente y simple peromergetengo que resolver los conflictos de las confirmaciones iniciales y las confirmaciones duplicadas, por lo que para una o doscherry-pick, está bien "elegir", pero para más es demasiado detallado y la rama se volverá demasiado complejagit rebase --ontofuente
Otra opción podría ser fusionar con la estrategia nuestra con el commit antes del rango y luego una fusión 'normal' con el último commit de ese rango (o bifurcar cuando es el último). Supongamos que solo 2345 y 3456 confirmaciones de master se fusionan en la rama de características:
en rama de características:
fuente