¿Qué significa elegir un compromiso con Git?

2340

Recientemente, me han pedido cherry-pickun compromiso.

Entonces, ¿qué significa elegir un commit en git? ¿Cómo lo haces?

Rahul
fuente
13
En lugar de fusionar, es más fácil volver a comprometerse desde una rama a la rama de destino (por ejemplo, maestro).
Levent Divilioglu

Respuestas:

2859

Escoger cerezas en Git significa elegir una confirmación de una rama y aplicarla en otra.

Esto está en contraste con otras formas como mergey rebaseque normalmente aplican muchas confirmaciones en otra rama.

  1. Asegúrese de estar en la rama a la que desea aplicar el compromiso.

    git checkout master
    
  2. Ejecute lo siguiente:

    git cherry-pick <commit-hash>
    

NÓTESE BIEN:

  1. Si elige una rama pública, debería considerar usar

    git cherry-pick -x <commit-hash>
    

    Esto generará un mensaje de confirmación estandarizado. De esta manera, usted (y sus compañeros de trabajo) aún pueden realizar un seguimiento del origen del compromiso y pueden evitar conflictos de fusión en el futuro.

  2. Si tiene notas adjuntas a la confirmación, no siguen la selección de cereza. Para traerlos también, debe usar:

    git notes copy <from> <to>
    

Enlaces adicionales:

Philip Fourie
fuente
247
Si elige una rama pública, debería considerar usarla git cherry-pick -x <commit-hash>. Esto generará un mensaje de confirmación estandarizado. De esta manera, usted (y sus compañeros de trabajo) aún pueden realizar un seguimiento del origen del compromiso y pueden evitar conflictos de fusión en el futuro.
MBober
2
¿Es realmente necesario cosechar cerezas? ¿Un restablecimiento mixto o un restablecimiento parcial no harán un trabajo similar?
Nav
10
Tenga en cuenta que si tiene notas adjuntas a la confirmación, no siguen la selección de cereza. Tienes que usar git notes copy <from> <to>para traerlos también.
Zitrax
55
git push es el último paso para realizar cambios en master
siéntete bien y programa el
58
FYI: Una confirmación contiene semánticamente todos los archivos del árbol de trabajo de ese momento (y el hash de confirmación de la confirmación anterior), por lo que no está aplicando una confirmación completa a otra confirmación, pero los cambios que hizo una confirmación en la confirmación anterior "cherry-pick commit applies the changes introduced by the named commit on the current branch"La mayoría ppl tiende a pensar en commit como cambios (como svn era iirc), pero no lo es, cada commit se refiere al árbol de trabajo completo. Aunque esto no hace una diferencia en este caso, puede ayudar a entender por qué git funciona como lo hace.
Emile Vrijdags
314

Esta cita está tomada de; Control de versiones con Git (libro realmente genial, te animo a que lo compres si estás interesado en git)

Editar: Dado que esta respuesta todavía está teniendo impresión, me gustaría agregar un video tutorial muy bueno en acción al respecto:

Youtube: Introducción a Git cherry-pick

Uso de git cherry-pick El comando git cherry-pick commit aplica los cambios introducidos por el commit con nombre en la rama actual. Introducirá una nueva confirmación distinta. Hablando estrictamente, el uso de git cherry-pick no altera el historial existente dentro de un repositorio; en cambio, se agrega a la historia. Al igual que con otras operaciones de Git que introducen cambios a través del proceso de aplicación de un diff, es posible que deba resolver conflictos para aplicar completamente los cambios de la confirmación dada . El comando git cherry-pick se usa típicamente para introducir confirmaciones particulares de una rama dentro de un repositorio en una rama diferente. Un uso común es reenviar las confirmaciones de puerto de una rama de mantenimiento a una rama de desarrollo.

$ git checkout rel_2.3
$ git cherry-pick dev~2 # commit F, above

antes de: antes de

después: después

Teoman shipahi
fuente
12
cuando los compromisos seleccionados son tomados en alguna rama (b1) y luego entregados al maestro. Y si la rama b1 (de la cual se seleccionaron originalmente las confirmaciones) también se intenta entregar al maestro. ¿Qué hay de los conflictos? ¿Eso se cuida o cómo funciona?
Parásito
3
@parasrish Sí, ya se han cuidado con sus fusiones anteriores. Entonces hiciste cambios a, b, c, d de (b1) rama. Tu cereza escogió solo "c". Luego, en el futuro, una vez que se fusione de (b1) a maestro, ya que los cambios "c" son los mismos, solo fusionará a, b, dy permanecerán los cambios "c". Pero si revierte la fusión, volverá a los cambios con "c". Necesitará hacerlos retroceder por separado.
Teoman shipahi
12
Debe enfatizarse: en el ejemplo dado, solo la diferencia (F - E) se aplica a Z. Ese es un caso estrecho. Cherry-pick puede usarse para aplicar las diferencias de múltiples confirmaciones, por ejemplo, todas las diferencias entre dos confirmaciones no adyacentes. Por ejemplo, siguiendo desde arriba, (F - E), (E - D), (D - C) y (C - B). Eso es equivalente a aplicar la diferencia (F - B).
Thomas Bitonti
2
Además, ¿qué sucede si el commit seleccionado (F en el ejemplo) tiene más de un predecesor inmediato?
Thomas Bitonti
2
@ j2emanue en otras palabras, cherry-pick solo tomará cambios de last-commit. Si se compromete 3 veces diferentes, y si elige la última, no tendrá cambios en la primera y segunda confirmación. El comando Fusionar tomará todos sus cambios y se aplicará a su rama objetivo (maestra).
Teoman shipahi
157

La selección de cerezas en Git está diseñada para aplicar algunas confirmaciones de una rama a otra. Se puede hacer si, por ejemplo. cometió un error y cometió un cambio en una rama equivocada, pero no desea fusionar toda la rama. Solo puedes, por ejemplo. revierta el commit y selecciónelo en otra rama.

Para usarlo, solo necesita git cherry-pick hashsaber dónde hashestá un hash de confirmación de otra rama.

Para ver el procedimiento completo, consulte: http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html

Tadeck
fuente
96

Breve ejemplo de situación, cuando necesitas recoger cerezas

Considere el siguiente escenario. Tienes dos ramas

a) release1 : esta rama va a su cliente, pero todavía hay algunos errores que corregir.

b) maestro : rama maestra clásica, donde puede, por ejemplo, agregar funcionalidad para la versión 2.

AHORA : arreglas algo en la versión 1 . Por supuesto, necesita esta solución también en master . Y ese es un caso de uso típico para la recolección de cerezas. Entonces, la selección de cereza en este escenario significa que toma una confirmación de la rama release1 e la incluye en la rama maestra .

Daniel Perník
fuente
3
Es posible que solo necesites lo contrario. Arreglaste un error en master y deberías elegirlo para liberarlo1. También podrían ser repositorios en lugar de ramas
canbax
1
¿Por qué no usar merge para ello?
FreeLightman
Yo quisiera: crear una versión de ramificación, arreglarla en la rama, fusionar la rama en la versión, fusionar la versión en master.
Jasper-M
57

cherry-pick es una característica de Git. Si alguien quiere comprometer compromisos específicos en una rama a una rama de destino, se utiliza cherry-pick.
Los pasos de git cherry-pick son los siguientes.

  1. pago (cambiar a) rama de destino.
  2. git cherry-pick <commit id>
    

    Aquí commit id es el id de actividad de otra rama.

    git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
    
  3. empujar a la rama objetivo

Visita https://git-scm.com/docs/git-cherry-pick

Vijay SB
fuente
44

Preparé ilustraciones paso a paso de lo que hace cherry-pick , y una animación de estas ilustraciones (casi al final).

  1. Antes de la selección de cereza
    (vamos a hacer una selección de cereza del compromiso Lde la rama feature): ingrese la descripción de la imagen aquí

  1. Inicio del comando git cherry-pick feature~2
    ( feature~2es el commit antes
    feature, es decir, el commit L): ingrese la descripción de la imagen aquí

  1. Después de ejecutar el comando ( git cherry-pick feature~2): ingrese la descripción de la imagen aquí

El mismo animado: ingrese la descripción de la imagen aquí


Nota:

El commit L'es desde el punto de vista del usuario (commit = instantánea) la copia exacta del commit L.

Técnicamente (internamente), es una confirmación nueva y diferente (porque, por ejemplo, Lcontiene un puntero a K(como su padre), mientras que L'contiene un puntero a E).

MarianD
fuente
¿Significa que L 'será N -> M -> L en la rama maestra? o traerá exclusivamente commit L en la rama maestra
Priyank Thakkar
1
@PriyankThakkar, sí, exclusivamente L , nada más (como se puede ver en las imágenes / animación).
MarianD
22

Puede pensar si una selección de cereza es similar a un rebase, o más bien se gestiona como un rebase. Con esto, quiero decir que toma una confirmación existente y la regenera tomando, como punto de partida, el jefe de la rama en la que se encuentra actualmente.

A rebasetoma una confirmación que tenía una X primaria y la regenera como si realmente tuviera una Y primaria, y esto es precisamente lo que cherry-pickhace.

La selección de cereza es más sobre cómo seleccionar las confirmaciones. Con pull(rebase), git regenera implícitamente sus confirmaciones locales además de lo que se extrae de su rama, pero con cherry-pickusted elige explícitamente algunas confirmaciones y las regenera implícitamente encima de su rama actual.

Entonces, la forma en que lo haces es diferente, pero en el fondo son operaciones muy similares: la regeneración de commits.

Hugh
fuente
1
Creo que esta es una visión bastante útil de las cosas. Implica por qué se cherry-pickcomporta de la manera en que lo hace cuando la rama de destino se fusiona nuevamente en la rama de origen. Gracias Señor.
Aluan Haddad
3
Me gustaría usar Cherry Pick en lugar de Git Merge después de que se realiza una función. todos siempre hacen git merge feature_branch cuando completan una característica. ¿Por qué no usar el comando cherry-pick? ¿tiene alguna idea por qué molestarse aplastando las confirmaciones si puedo cereza escoger?
j2emanue
11

Es algo así como Copiar (desde algún lugar) y Pegar (hacia algún lugar), pero para confirmaciones específicas.

Si desea hacer una reparación, por ejemplo, puede usar la cherry-pickfunción.

Haz tu cherry-picken una rama de desarrollo, y mergeeso se compromete con una rama de lanzamiento. Del mismo modo, haga una cherry-pickdesde una rama de lanzamiento a master. Voila

Ajeet Sharma
fuente
11

Cuando trabajas con un equipo de desarrolladores en un proyecto, administrar los cambios entre varias ramas de git puede convertirse en una tarea compleja. A veces no desea fusionar una rama completa en otra, y solo necesita elegir una o dos confirmaciones específicas. Este proceso se llama 'recolección de cerezas'.

Encontré un gran artículo sobre la recolección de cerezas, échale un vistazo para obtener detalles en profundidad: https://www.previousnext.com.au/blog/intro-cherry-picking-git

Wolfack
fuente
7

Si desea fusionar sin ID de confirmación, puede usar este comando

git cherry-pick master~2 master~0

El comando anterior fusionará las últimas tres confirmaciones del maestro de 1 a 3

Si desea hacer esto para un solo compromiso, simplemente elimine la última opción

git cherry-pick master~2

De esta manera, fusionarás el tercer commit desde el final del master.

Cuentas
fuente
Esto es confuso. Creo que aquí estás en una rama que no sea maestra, ¿verdad? Y cuando menciona dos confirmaciones, se refiere a las confirmaciones <from> y <to> para definir el rango que desea seleccionar. ¿Correcto? Sería de gran ayuda si se describe el escenario. Buena adición sin embargo. Gracias.
Saurabh Patil
6

Aplicará un compromiso particular a su rama actual.

Esto significa :

  • todos los archivos agregados por este commit serán agregados
  • todos los archivos eliminados por este commit serán eliminados
  • todos los archivos modificados por este commit se fusionarán. ¡Esto significa todo el archivo del commit, no solo los cambios de este commit!

Ej: Considerar cometer A

added newFileA
modified main:
+ import './newFileA'

cometer B

added newFileB
modified main:
+ import './newFileB'

Si elige la confirmación B en otra rama, terminará con:

/newFileB
/main :
   import './newFileA'
   import './newFileB'

ya que commit B contiene newFileB y main , pero no newFileA , lo que resulta en un error, así que úselo con precaución.

mandelf
fuente
0

Extracto de los documentos oficiales:

Dado uno o más compromisos existentes, aplique el cambio que cada uno introduce, registrando un nuevo compromiso para cada uno. Esto requiere que su árbol de trabajo esté limpio (sin modificaciones de la confirmación HEAD).

Cuando no es obvio cómo aplicar un cambio, sucede lo siguiente:

  1. La rama actual y el puntero HEAD permanecen en la última confirmación realizada con éxito.

  2. La referencia CHERRY_PICK_HEAD está configurada para apuntar a la confirmación que introdujo el cambio que es difícil de aplicar.

  3. Las rutas en las que el cambio aplicado limpiamente se actualizan tanto en el archivo de índice como en su árbol de trabajo.

  4. Para rutas conflictivas, el archivo de índice registra hasta tres versiones, como se describe en la sección "VERDADERO FUSIÓN" de git-merge. Los archivos del árbol de trabajo incluirán una descripción del conflicto entre corchetes por los marcadores de conflicto habituales <<<<<<< y >>>>>>>.

No se realizan otras modificaciones.

Lee mas...

Saikat
fuente