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
B
travé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 --onto
serí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 laworking
rama)a "
tmp
" (que señala hacia dóndeintegration
apuntaba 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 laintegration
rama en latmp
rama)Después de eso
rebase --onto
,integration
volverá 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-pick
se 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
-m
opción, ¿cómo maneja esos compromisos? ¿O hay una manera de filtrar estos commits?-m
Se supone que @aug los manejará por usted, seleccionando la línea principal a la que hace referencia el-m
parámetro que ha elegido para esta selección de cerezas.-m
opción solo cuando llegue a una confirmación principal cuando se selecciona una variedad de confirmaciones? En este momento, si paso-m
comogit cherry-pick a87afaaf..asfa789 -m 1
se 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 --continue
y 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..B
no obtendrá el commit A (lo necesitaríaA~1..B
para 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 C
no funciona como cabría esperar, ingenuamente. ¡No elegirá todo en el rangoA..B
y se comprometeráC
! Para hacer esto, debe dividirse en dos líneas, primerogit cherry-pick A..B
y 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
--3way
agit-am
si 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-pick
para 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-pick
Es ú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
: ABCDE
niH
Pasos para copiar características sin los pasos E y H en la rama
dev_feature_wo_E_H
git checkout dev
git checkout -b dev_feature_wo_E_H
git rebase --interactive --rebase-merges --no-ff D
donde pusedrop
delanteE
yH
en el editor de rebasecommit
Pasos para copiar la rama
dev_feature_wo_E_H
en el destino.git checkout target
git merge --no-ff --no-commit dev_feature_wo_E_H
commit
Algunas observaciones
cherry-pick
en los días anterioresgit cherry-pick
es potente y simple peromerge
tengo 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 --onto
fuente
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