multiple - git cherry-pick dice "... 38c74d es una combinación pero no se dio la opción-m"
how to do cherry pick in git (4)
Hice algunos cambios en mi rama maestra y quiero traerlos hacia arriba. Sin embargo, cuando selecciono las siguientes confirmaciones, me quedo atascado en fd9f578 donde git dice:
$ git cherry-pick fd9f578
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given.
¿Qué es lo que git está tratando de decirme y es lo mejor para usar aquí? La rama maestra incluye cambios en los archivos que se han modificado en la rama ascendente, por lo que estoy seguro de que habrá algunos conflictos de combinación, pero no están tan mal como para corregirlos. Sé qué cambios se necesitan donde.
Estos son los compromisos que quiero traer en sentido ascendente.
e7d4cff added some comments...
23e6d2a moved static strings...
44cc65a incorporated test ...
40b83d5 whoops delete whitspace...
24f8a50 implemented global.c...
43651c3 cleaned up ...
068b2fe cleaned up version.c ...
fd9f578 Merge branch ''master'' of ssh://extgit/git/sessions_common
4172caa cleaned up comments in sessions.c ...
La forma en que funciona una selección de cerebros es tomar la diferencia que representa un conjunto de cambios (la diferencia entre el árbol de trabajo en ese punto y el árbol de trabajo de su padre), y aplicarlo a su rama actual.
Entonces, si un compromiso tiene dos o más padres, también representa dos o más diferencias, ¿cuál se debe aplicar?
Estás tratando de elegir fd9f578
, que fue una fusión con dos padres. Por lo tanto, debe indicar al comando cherry-pick cuál contra el cual debe calcularse la diferencia, utilizando la opción -m
. Por ejemplo, git cherry-pick -m 1 fd9f578
para usar parent 1 como base.
No puedo asegurarlo para su situación particular, pero usar git merge
lugar de git cherry-pick
es generalmente recomendable. Cuando selecciona un compromiso de fusión, colapsa todos los cambios realizados en el padre que no especificó para -m
en ese compromiso . Pierdes toda su historia, y reúnes todas sus diferencias. Tu llamada.
La respuesta de @Borealid es correcta, pero suponga que no le importa conservar el historial de fusión exacto de una rama y simplemente quiere elegir una versión linealizada de la misma. Aquí hay una manera fácil y segura de hacer eso:
Estado de inicio: usted está en la rama X
, y desea seleccionar los compromisos Y..Z
.
-
git checkout -b tempZ Z
-
git rebase Y
-
git checkout -b newX X
-
git cherry-pick Y..tempZ
- (opcional)
git branch -D tempZ
Lo que esto hace es crear una rama tempZ
basada en Z
, pero con el historial de Y
adelante linealizado, y luego seleccionarlo en una copia de X
llamada newX
. (Es más seguro hacer esto en una nueva rama en lugar de mutar X
). Por supuesto, puede haber conflictos en el paso 4, que tendrá que resolver de la forma habitual ( cherry-pick
funciona de manera muy similar a la rebase
en ese sentido). ). Finalmente se borra la rama temporal tempZ
.
Si el paso 2 muestra el mensaje "La rama actual actual está actualizada", entonces Y..Z
ya era lineal, por lo que simplemente ignore ese mensaje y continúe con los pasos 3 en adelante.
Luego revisa newX
y ve si eso hizo lo que querías.
(Nota: esto no es lo mismo que un simple git rebase X
cuando se encuentra en la rama Z
, ya que no depende de ninguna manera de la relación entre X
e Y
; puede haber confirmaciones entre el ancestro común y la Y
que usted no hizo. t quiere)
La simplificación del método @Daira Hopwood es buena para elegir un solo compromiso. No necesita sucursales temporales.
En el caso del autor:
- Z se quiere cometer (fd9f578)
- Y se compromete antes
- X rama de trabajo actual
entonces hazlo:
git checkout Z # move HEAD to wanted commit
git reset Y # have Z as changes in working tree
git stash # save Z in stash
git checkout X # return to working branch
git stash pop # apply Z to current branch
git commit -a # do commit
Aquí hay una nueva versión de la respuesta aceptada que idealmente aclara las ventajas / riesgos de los posibles enfoques:
Estás tratando de elegir fd9f578, que fue una fusión con dos padres.
En lugar de elegir una combinación, lo más simple es elegir los compromisos que realmente desea de cada rama de la combinación.
Dado que ya se ha fusionado, es probable que todas las confirmaciones deseadas estén en su lista. Cúbralos directamente y no tiene que meterse con la confirmación de fusión.
explicación
La forma en que funciona un pick-cherry es tomar la diferencia que representa un conjunto de cambios (la diferencia entre el árbol de trabajo en ese punto y el árbol de trabajo de su padre) y aplicar el conjunto de cambios a su rama actual.
Si un compromiso tiene dos o más padres, como es el caso de una combinación, ese compromiso también representa dos o más diferencias. El error se produce debido a la incertidumbre sobre la que debe aplicarse diff.
alternativas
Si determina que necesita incluir la combinación frente a la selección selectiva de las confirmaciones relacionadas, tiene dos opciones:
(Más complicado y oscuro; también descarta el historial) puede indicar qué padre debe aplicar.
Usa la opción
-m
para hacerlo. Por ejemplo,git cherry-pick -m 1 fd9f578
usará el primer padre listado en la combinación como la base.También tenga en cuenta que cuando selecciona un compromiso de fusión, colapsa todos los cambios realizados en el padre que no especificó para
-m
en ese compromiso . Pierdes toda su historia, y reúnes todas sus diferencias. Tu llamada.
(Más simple y más familiar; conserva el historial) puede usar
git merge
lugar degit cherry-pick
.- Como es habitual con
git merge
, intentará aplicar todas las confirmaciones que existen en la rama que está fusionando y las incluirá individualmente en su registro de git.
- Como es habitual con