Rebase y rebase interactivo trabajan con el conjunto de commits de una rama: los descomponen, los reordenan, los reaplican. git cherry-pick hace algo mucho más quirúrgico: coge un commit concreto, esté donde esté, y aplica su cambio sobre la rama en la que estás ahora, creando un commit nuevo.

El nombre lo dice todo: cherry-picking es escoger las cerezas una a una. Y como toda herramienta quirúrgica, es excelente en manos que saben cuándo usarla y peligrosa en manos que la usan por costumbre. Un cherry-pick mal puesto duplica trabajo, confunde el historial y provoca conflictos absurdos meses después.

Ana lo necesita hoy. Ha corregido en main el fallo de que el foco se pierde al borrar una tarea, y la versión 1.x que sigue desplegada en el cliente tiene el mismo fallo pero vive en una rama de mantenimiento aparte, que no puede recibir todo lo que hay en main. Quiere ese commit y nada más.

Contenido

  1. Qué hace git cherry-pick
  2. El caso de Ana: llevar una corrección a mantenimiento
  3. Varios commits y rangos
  4. Opciones útiles: -n, -x, -e, -s
  5. Conflictos al hacer cherry-pick
  6. Rescatar un commit de una rama abandonada
  7. El problema de los duplicados
  8. Detectar duplicados: git cherry y --cherry-mark
  9. Cuándo NO usar cherry-pick

  1. Qué hace git cherry-pick

git cherry-pick <sha>

Git toma el diff que introduce <sha> (es decir, la diferencia entre ese commit y su padre), lo aplica sobre el estado actual de tu rama y crea un commit nuevo con ese cambio.

La palabra clave, otra vez, es nuevo. Igual que en el rebase (lección 05-01), y por el mismo motivo del modelo de datos de la lección 01-04: el commit resultante tiene otro padre, luego otro contenido, luego otro hash. No es "el mismo commit en dos ramas": son dos commits distintos que casualmente introducen el mismo cambio.

gitGraph
   commit id: "1a4c8d6"
   commit id: "8b6d3c2"
   branch mantenimiento/1.x
   commit id: "e4f7b91"
   checkout main
   commit id: "c5d9b1e"
   commit id: "7d3a8f4"
   checkout mantenimiento/1.x
   cherry-pick id: "7d3a8f4"

El diagrama miente un poco a propósito, porque gitGraph reutiliza la etiqueta del commit original. En realidad, en mantenimiento/1.x aparece un commit distinto, con hash b9e2c17, que introduce el mismo cambio que 7d3a8f4. Recuérdalo cada vez que veas un diagrama de cherry-pick: la flecha punteada significa "el mismo cambio", nunca "el mismo objeto".

Qué se conserva y qué no, para completar la tabla mental que empezaste en 05-01:

Elemento ¿Se conserva?
Mensaje Sí (editable con -e)
Autor y correo : sigue siendo de quien lo escribió
Fecha de autoría
Confirmador y su fecha No: pasas a serlo tú, ahora
Contenido del cambio Sí, si no hay conflicto
Padre y hash No

Que se conserve la autoría es importante: cuando llevas la corrección de un compañero a otra rama, el crédito sigue siendo suyo.

  1. El caso de Ana: llevar una corrección a mantenimiento

El repositorio de gestor-tareas tiene dos líneas vivas:

  • main, donde se desarrolla la versión 2.
  • mantenimiento/1.x, que reproduce lo que está desplegado en el cliente y solo recibe correcciones.

Ana corrigió el fallo del foco en main:

git switch main
git log --oneline -3
7d3a8f4 (HEAD -> main, origin/main) Devolver el foco al campo de texto tras borrar una tarea
c5d9b1e Extraer la creación del elemento de tarea a su función
8b6d3c2 Guardar las tareas en localStorage

El commit es pequeño y autocontenido, que es exactamente lo que hace a un commit buen candidato para cherry-pick:

git show 7d3a8f4
commit 7d3a8f4...
Author: Ana Ferrer <[email protected]>
Date:   Wed Jul 29 11:42:08 2026 +0200

    Devolver el foco al campo de texto tras borrar una tarea

diff --git a/app.js b/app.js
--- a/app.js
+++ b/app.js
@@ -48,6 +48,7 @@ function borrarTarea(id) {
   tareas = tareas.filter(function (t) { return t.id !== id; });
   guardarTareas();
   pintarLista();
+  document.getElementById('nueva-tarea').focus();
 }

Ahora, el trasplante:

# 1. Situarse en la rama de destino
git switch mantenimiento/1.x
git log --oneline -2
e4f7b91 (HEAD -> mantenimiento/1.x, origin/mantenimiento/1.x) Corregir el formato de la fecha en el listado
8b6d3c2 Guardar las tareas en localStorage
# 2. Traer solo ese commit, dejando constancia del origen
git cherry-pick -x 7d3a8f4
[mantenimiento/1.x b9e2c17] Devolver el foco al campo de texto tras borrar una tarea
 Date: Wed Jul 29 11:42:08 2026 +0200
 1 file changed, 1 insertion(+)
# 3. Comprobar el resultado
git show b9e2c17
commit b9e2c17...
Author: Ana Ferrer <[email protected]>
Date:   Wed Jul 29 11:42:08 2026 +0200

    Devolver el foco al campo de texto tras borrar una tarea

    (cherry picked from commit 7d3a8f4c9b1e5d2a8f7c3b6e9d4a1c8f5b2e7d3a)

diff --git a/app.js b/app.js
...

Hash nuevo (b9e2c17), autoría de Ana intacta, cambio idéntico, y una línea al final del mensaje que dice de dónde vino. Esa línea la ha puesto -x, y merece su apartado.

  1. Varios commits y rangos

git cherry-pick acepta varios commits sueltos y rangos.

# Varios commits sueltos, en el orden indicado
git cherry-pick 7d3a8f4 c5d9b1e 4e7f2a9

Se aplican en el orden en que los escribes, no en orden cronológico. Si dependen unos de otros, escríbelos en el orden en que se hicieron o tendrás conflictos evitables.

Los rangos usan la misma notación de dos puntos de la lección 02-06, y con la misma trampa:

# Del commit SIGUIENTE a A, hasta B (ambos inclusive salvo A)
git cherry-pick A..B

# Desde A INCLUIDO hasta B
git cherry-pick A^..B
Expresión Commits aplicados
A..B Los posteriores a A hasta B. A NO se incluye
A^..B Igual, pero A sí se incluye
B Solo B
B~3..B Los tres últimos hasta B
--stdin Los que le pases por la entrada estándar, uno por línea

Ejemplo con nombres reales: Bruno quiere llevar a mantenimiento los tres commits de correcciones que hizo en funcionalidad/exportacion-csv, que van de 6e1d9f3 a 9c7e5a1:

git switch mantenimiento/1.x
git cherry-pick -x 6e1d9f3^..9c7e5a1
[mantenimiento/1.x 3a8f2d5] Añadir la conversión de tareas a formato CSV
[mantenimiento/1.x 7b4e9c1] Descargar el CSV generado desde el navegador
[mantenimiento/1.x d62a4f8] Añadir el botón de exportar a la barra de acciones

Tres commits nuevos con tres hashes nuevos, en el orden correcto.

Un aviso importante: un rango de cherry-pick no incluye los commits de fusión. Si el rango contiene una fusión, Git la salta silenciosamente (o falla, según el caso). Trasplantar un commit de fusión requiere -m para elegir el padre respecto al cual calcular el diff, igual que en revert (lección 05-06), y casi nunca es lo que quieres. Si tu rango tiene fusiones, probablemente lo que buscabas era un merge o un rebase.

  1. Opciones útiles: -n, -x, -e, -s

Opción Nombre largo Qué hace
-n --no-commit Aplica los cambios al directorio de trabajo y al índice, sin confirmar
-x Añade (cherry picked from commit <sha>) al mensaje
-e --edit Abre el editor para modificar el mensaje
-s --signoff Añade una línea Signed-off-by: Nombre <correo>
--ff Si el commit es hijo directo de HEAD, hace fast-forward en vez de crear uno nuevo
--strategy-option -X ours / -X theirs Resolución automática de conflictos por un lado
--allow-empty Permite crear el commit aunque no aporte cambios

-n (--no-commit) sirve para agrupar. Si quieres que cinco commits pequeños lleguen a la rama de destino como uno solo:

git cherry-pick -n 6e1d9f3 b8c2a70 9c7e5a1
git status --short
M  app.js
M  index.html
M  estilos.css
git commit -m "Portar las correcciones de la exportación CSV a la rama 1.x"

Los tres cambios quedan preparados en el índice y tú decides cuándo y con qué mensaje confirmarlos. Si te arrepientes a mitad, git cherry-pick --abort deshace todo lo acumulado.

-x es fundamental en ramas de mantenimiento y es la razón por la que existe la opción. Deja una nota en el mensaje que permite, meses después, contestar a la pregunta "¿de dónde salió este commit?":

Devolver el foco al campo de texto tras borrar una tarea

(cherry picked from commit 7d3a8f4c9b1e5d2a8f7c3b6e9d4a1c8f5b2e7d3a)

Con esa línea, git show 7d3a8f4 te lleva al original y puedes ver su contexto completo. Sin ella, el commit aparece en la rama de mantenimiento sin explicación posible.

Cuidado con un matiz: -x solo tiene sentido cuando el commit de origen es público. Si copias un commit de una rama local que vas a borrar, la referencia apuntará a un hash que nadie más puede resolver, y la nota confunde más que ayuda. La documentación de Git es explícita en esto: úsalo para copiar de una rama pública a otra.

-s añade la línea Signed-off-by:, una convención de proyectos que exigen certificar el origen de las aportaciones (el Developer Certificate of Origin del núcleo de Linux es el caso canónico). No es una firma criptográfica; eso son las etiquetas y commits firmados con GPG, que se ven en la lección 08-05.

  1. Conflictos al hacer cherry-pick

Un cherry-pick aplica un parche sobre un contexto que puede haber cambiado. Es muy normal que conflictúe, sobre todo cuando la rama de destino ha divergido mucho.

git cherry-pick -x 7d3a8f4
Auto-merging app.js
CONFLICT (content): Merge conflict in app.js
error: could not apply 7d3a8f4... Devolver el foco al campo de texto tras borrar una tarea
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
hint: You can instead skip this commit with "git cherry-pick --skip".
hint: To abort and get back to the state before "git cherry-pick",
hint: run "git cherry-pick --abort".

La mecánica de resolución —marcadores, git status, editar, git add— es la de la lección 03-05 y no cambia. Lo específico es cómo se sale:

Comando Qué hace
git cherry-pick --continue Confirma el commit con tu resolución y sigue con el siguiente del rango
git cherry-pick --skip Descarta ese commit y sigue con el resto
git cherry-pick --abort Cancela toda la operación y devuelve la rama a su estado inicial
git cherry-pick --quit Sale del estado de cherry-pick pero conserva lo ya aplicado

Y aquí, buena noticia: en un cherry-pick, ours y theirs NO están invertidos. ours es tu rama de destino (donde estás) y theirs es el commit que estás trayendo, que es lo intuitivo. La inversión de la lección 05-01 es una peculiaridad del rebase, no una regla general.

# Durante un conflicto de cherry-pick
git checkout --ours app.js      # la versión de mi rama de destino
git checkout --theirs app.js    # la versión del commit que traigo

Si el conflicto te parece muy grande para el tamaño del cambio, es una señal: probablemente estés portando un commit que depende de otro que no has portado. Mira git log --oneline <origen> alrededor del commit y comprueba si hay un commit previo que también hace falta.

Cuando el commit conflictúa porque su cambio ya está aplicado en la rama de destino, Git te lo dice de otra forma:

The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

    git commit --allow-empty

Ahí, git cherry-pick --skip es la respuesta correcta: no hay nada que aportar.

  1. Rescatar un commit de una rama abandonada

El segundo caso legítimo. Carla empezó funcionalidad/etiquetas-color y el equipo decidió aparcarla: el enfoque no convencía. Pero dentro había un commit que sí valía: una función que valida el formato hexadecimal de un color y que resulta útil para otra cosa.

# 1. Buscar el commit en la rama abandonada
git log --oneline funcionalidad/etiquetas-color
92c7a06 Pintar la etiqueta de color en el listado
d5e8f31 Anadir el campo color al modelo de tarea
5f1c4b8 Añadir la validación de colores hexadecimales
e91d4a8 Extraer la creación del elemento de tarea a su función
# 2. Ver qué hace exactamente antes de trasplantarlo
git show 5f1c4b8 --stat
 app.js | 12 ++++++++++++
 1 file changed, 12 insertions(+)
# 3. Trasplantarlo a main
git switch main
git cherry-pick 5f1c4b8
[main 8c3e7f1] Añadir la validación de colores hexadecimales
 1 file changed, 12 insertions(+)

Aquí Carla no ha usado -x, y hace bien: la rama de origen se va a borrar, así que dejar en el mensaje una referencia a un hash que quedará huérfano no ayuda a nadie. En estos casos, si quieres dejar constancia, escríbela en lenguaje humano con -e:

git cherry-pick -e 5f1c4b8
Añadir la validación de colores hexadecimales

Rescatado de la rama funcionalidad/etiquetas-color, que se descartó
por otros motivos. La función es útil de forma independiente.

Un tercer caso, para completar el catálogo de usos legítimos: te has equivocado de rama. Has hecho tres commits en main que debían ir en una rama de funcionalidad. La solución clásica es crear la rama donde estás, y devolver main a su sitio; pero si prefieres no tocar main, un cherry-pick de los tres commits a la rama correcta es una salida perfectamente válida. La casuística completa de "he confirmado en la rama equivocada" está en la lección 09-01.

  1. El problema de los duplicados

Aquí es donde el cherry-pick pasa factura, y conviene entenderlo bien porque es la razón principal para no abusar de él.

Escenario: Bruno tiene funcionalidad/informe-semanal con cinco commits. Uno de ellos, 4d7c1a9, corrige un fallo que urge en producción ya. Bruno hace cherry-pick de ese commit a main:

git switch main
git cherry-pick 4d7c1a9
[main 2e9b6f3] Corregir el cálculo de tareas vencidas

Perfecto: el fallo está corregido en main y desplegado. Pero ahora, en el repositorio, el mismo cambio existe dos veces: como 4d7c1a9 en la rama de Bruno y como 2e9b6f3 en main.

gitGraph
   commit id: "e91d4a8"
   branch funcionalidad/informe-semanal
   commit id: "a1c5e83"
   commit id: "4d7c1a9"
   commit id: "6f2b9d4"
   checkout main
   commit id: "2e9b6f3"

Dos semanas después, Bruno termina la funcionalidad y fusiona su rama en main. ¿Qué pasa?

Caso bueno. Si nadie ha tocado esas líneas desde entonces, la fusión a tres bandas se da cuenta de que el cambio de 4d7c1a9 ya está aplicado en main (el resultado es el mismo por los dos lados) y la fusión sale limpia. El commit 4d7c1a9 entra en el historial, pero su contenido no se aplica dos veces. El resultado es correcto; simplemente el git log de main muestra dos commits que dicen lo mismo.

Caso malo. Si alguien ha modificado esas líneas en main después del cherry-pick, la fusión ve un cambio en theirs (el de 4d7c1a9) sobre una base que ya no coincide, y conflictúa. Es el conflicto más desconcertante que existe: los marcadores muestran dos versiones casi idénticas de un código que tú ya arreglaste, y no hay forma de entender por qué choca si no recuerdas el cherry-pick de hace dos semanas.

Caso peor. Si el cambio no es idempotente —añadir una línea a una lista, incrementar un contador, añadir una entrada a un fichero de configuración—, la fusión puede aplicarlo dos veces sin conflictuar. El resultado compila, pasa los tests superficiales y está mal.

La conclusión es la que da título al último apartado: cherry-pick es para cuando no vas a fusionar después, o para cuando fusionar no es una opción (ramas que nunca se juntan, como main y mantenimiento/1.x).

  1. Detectar duplicados: git cherry y --cherry-mark

Git tiene herramientas para reconocer commits que introducen el mismo cambio con hashes distintos. Se basan en el patch-id: un hash calculado sobre el contenido del diff, ignorando el contexto, las líneas en blanco y los números de línea. Dos commits con el mismo patch-id hacen lo mismo aunque sean objetos distintos.

git cherry compara dos ramas y marca cada commit con + (no está en la otra) o - (ya está allí, con otro hash):

git cherry -v main funcionalidad/informe-semanal
+ a1c5e83f2b7d9c4e1a8f6b3d5c2e9a7f4b1d8c6e Añadir la vista del informe semanal
- 4d7c1a9e8b2f5d3c7a9e1f4b6d8c2a5e3f7b9d1c Corregir el cálculo de tareas vencidas
+ 6f2b9d4c1e7a3f8b5d2c9e6a4f1b8d3c7e5a2f9b Añadir el filtro por semana

El - en la segunda línea significa: "este commit ya está aplicado en main, aunque allí tenga otro hash". Exactamente lo que buscábamos. La sintaxis es git cherry [-v] <upstream> [<head>], y -v añade el asunto de cada commit.

Es especialmente útil antes de fusionar o antes de portar un lote de commits a mantenimiento: te dice qué queda realmente por llevar.

git log --cherry-mark hace lo mismo dentro de un log, sobre un rango de tres puntos:

git log --oneline --cherry-mark --left-right main...funcionalidad/informe-semanal
> a1c5e83 Añadir la vista del informe semanal
= 4d7c1a9 Corregir el cálculo de tareas vencidas
= 2e9b6f3 Corregir el cálculo de tareas vencidas
> 6f2b9d4 Añadir el filtro por semana
Marca Significado
< Solo en el lado izquierdo (main)
> Solo en el lado derecho (la rama)
= Presente en los dos lados como cambio equivalente (patch-id igual)

Ahí están, uno al lado del otro, los dos commits que hacen lo mismo. Variantes relacionadas:

# Ocultar los equivalentes: solo lo que de verdad falta por integrar
git log --oneline --cherry-pick --left-right main...funcionalidad/informe-semanal

# Atajo de lo anterior, solo el lado derecho
git log --oneline --cherry funcionalidad/informe-semanal...main

--cherry-pick es el que usarás más: filtra el ruido y te deja solo el trabajo pendiente de verdad.

Una limitación honesta: el patch-id compara el diff. Si al hacer el cherry-pick hubo un conflicto y resolviste de forma distinta, el diff resultante no será idéntico y Git no lo reconocerá como equivalente. La detección es una ayuda, no una garantía.

  1. Cuándo NO usar cherry-pick

Situación Qué hacer en su lugar
Quieres llevar toda una rama a otra git merge (o rebase si aún no está publicada)
Vas a fusionar esa rama después, más adelante Espera y fusiona: evitas los duplicados del apartado 7
Necesitas más de tres o cuatro commits seguidos rebase --onto: reaplica un tramo completo y no deja duplicados
Quieres poner tu rama al día con main git merge main o git rebase main, nunca cherry-picks sueltos de main
El commit depende de otros que no vas a llevar Portar también las dependencias, o rehacer el cambio a mano
Quieres "copiar" un commit a la misma rama Casi seguro que buscas revert (05-06) o un rebase interactivo

La regla de decisión, en una frase: si las dos ramas van a acabar juntándose, no copies commits entre ellas; fusiónalas. El cherry-pick es para ramas que viven en paralelo permanentemente (mantenimiento, versiones antiguas, entornos separados) o para rescatar algo de una rama que va a morir.

Sobre la regla de oro: el cherry-pick es de las tres operaciones de este bloque la menos peligrosa, porque no reescribe nada. Añade un commit nuevo a la rama donde estás; no toca el origen ni obliga a nadie a forzar un push. Su peligro no es la reescritura sino la duplicación, que se paga más tarde y en forma de conflictos difíciles de explicar.

Errores Comunes y Consejos

Error 1: creer que cherry-pick "mueve" el commit. Lo copia. El original sigue en su rama, tan vivo como antes. Si querías moverlo, tienes que borrarlo del origen con un rebase interactivo (drop), con las implicaciones de la regla de oro que eso conlleva.

Error 2: hacer cherry-pick de commits de una rama que después vas a fusionar. Es la fuente número uno de conflictos incomprensibles. Si la rama va a entrar entera, espera.

Error 3: olvidar -x al portar a mantenimiento. Dentro de seis meses, ese commit sin origen conocido en mantenimiento/1.x será un misterio. Cuesta dos caracteres.

Error 4: usar -x copiando de una rama local que vas a borrar. La referencia queda apuntando a un hash irresoluble. Ahí es mejor -e y una nota en lenguaje humano.

Error 5: hacer cherry-pick sin mirar el commit antes. git show <sha> cuesta tres segundos y te evita descubrir a mitad del conflicto que el commit tocaba seis ficheros y dependía de otros tres.

Error 6: no comprobar el rango. A..B excluye A. Si esperabas que se aplicaran cinco commits y se aplican cuatro, es esto. Comprueba siempre antes con git log --oneline A..B.

Error 7: confundir la dirección de git cherry. El primer argumento es el upstream (con lo que comparas, normalmente main) y el segundo la rama que examinas. Al revés te dará justo lo contrario de lo que esperas.

Consejo 1: haz commits pequeños y autocontenidos. No es un consejo sobre cherry-pick, es el consejo que hace posible el cherry-pick. Un commit que hace una sola cosa se trasplanta sin drama; uno que mezcla tres, no.

Consejo 2: verifica siempre después de portar. Que el parche se aplique sin conflicto no significa que funcione en la otra rama. Ejecuta las pruebas.

Consejo 3: usa git cherry -v antes de una campaña de portado. Te dirá exactamente qué queda por llevar y qué ya está, sin depender de tu memoria.

Consejo 4: para lotes grandes, git rebase --onto en lugar de muchos cherry-picks. Es la misma operación en el fondo, pero de una sola vez y con una lista clara de lo que se está reaplicando.

Consejo 5: si el cherry-pick se complica, aborta. git cherry-pick --abort deja el repositorio exactamente como estaba. Reconstruir el cambio a mano en la rama de destino es a veces más rápido y siempre más claro que pelear con un parche que no encaja.

Ejercicios

Ejercicio 1: portar una corrección a mantenimiento

Monta un repositorio con main y una rama mantenimiento/1.x que salga de un commit antiguo. Añade dos commits a main, uno de ellos una corrección pequeña. Después:

  1. Porta solo la corrección a mantenimiento/1.x dejando constancia del origen.
  2. Demuestra que el hash es distinto pero el diff es idéntico.
  3. Demuestra que el autor original se ha conservado.

Ejercicio 2: el duplicado y su detección

Provoca a propósito el problema del apartado 7:

  1. Crea una rama con tres commits.
  2. Haz cherry-pick del segundo a main.
  3. Usa git cherry -v para demostrar que Git sabe que ese cambio ya está en main.
  4. Usa git log --cherry-mark --left-right para ver los dos commits equivalentes marcados con =.
  5. Fusiona la rama en main y observa qué pasa con el historial.

Ejercicio 3: agrupar varios commits en uno

Con una rama que tenga cuatro commits pequeños, lleva los tres primeros a otra rama como un único commit con un mensaje propio, usando -n. Verifica con git show --stat que el commit resultante contiene los cambios de los tres.

Soluciones

Solución 1:

mkdir /tmp/practica-cherry && cd /tmp/practica-cherry
git init -b main
echo "v1" > app.js && git add . && git commit -m "Version inicial"

git switch -c mantenimiento/1.x
git switch main

printf 'v1\nfuncionalidad nueva\n' > app.js && git commit -am "Añadir funcionalidad de la version 2"
printf 'v1\nfuncionalidad nueva\ncorreccion\n' > app.js
git -c user.name="Ana Ferrer" -c user.email="[email protected]" commit -am "Corregir el foco tras borrar"

git log --oneline
5c9e1f4 Corregir el foco tras borrar
a72b8d3 Añadir funcionalidad de la version 2
1e4f7c9 Version inicial
# 1. Portar solo la corrección
git switch mantenimiento/1.x
git cherry-pick -x 5c9e1f4
Auto-merging app.js
CONFLICT (content): Merge conflict in app.js

(Conflictúa porque en mantenimiento/1.x falta la línea de la funcionalidad. Se resuelve dejando solo la corrección.)

printf 'v1\ncorreccion\n' > app.js
git add app.js
git cherry-pick --continue
# 2 y 3. Comparar
git log --oneline -1
git show --pretty='%h | %an | %ad' --date=short HEAD | head -4
git show --pretty='%h | %an | %ad' --date=short 5c9e1f4 | head -4
d81f6a2 Corregir el foco tras borrar
d81f6a2 | Ana Ferrer | 2026-07-29
5c9e1f4 | Ana Ferrer | 2026-07-29

Hash distinto, misma autoría y misma fecha de autoría. El mensaje del nuevo incluye además la línea (cherry picked from commit 5c9e1f4...).

Solución 2:

mkdir /tmp/practica-duplicados && cd /tmp/practica-duplicados
git init -b main
printf 'linea 1\n' > f.txt && git add . && git commit -m "Base"

git switch -c funcionalidad/algo
printf 'linea 1\nA\n' > f.txt && git commit -am "Commit A"
printf 'linea 1\nA\nB\n' > f.txt && git commit -am "Commit B (la correccion urgente)"
printf 'linea 1\nA\nB\nC\n' > f.txt && git commit -am "Commit C"

git log --oneline
9f2a7c1 Commit C
4d8e3b6 Commit B (la correccion urgente)
c17b5f9 Commit A
2e6a9d4 Base
# 2. Cherry-pick del segundo a main
git switch main
git cherry-pick 4d8e3b6
Auto-merging f.txt
CONFLICT (content): Merge conflict in f.txt
printf 'linea 1\nB\n' > f.txt
git add f.txt && git cherry-pick --continue
# 3. git cherry lo detecta
git cherry -v main funcionalidad/algo
+ c17b5f9... Commit A
- 4d8e3b6... Commit B (la correccion urgente)
+ 9f2a7c1... Commit C

Solo si el diff resultante coincide; si tu resolución del conflicto cambió el parche, aparecerá con +. Es la limitación que comentamos.

# 4. La vista con marcas
git log --oneline --cherry-mark --left-right main...funcionalidad/algo
< 7b3e9f1 Commit B (la correccion urgente)
> c17b5f9 Commit A
> 4d8e3b6 Commit B (la correccion urgente)
> 9f2a7c1 Commit C
# 5. La fusión
git merge funcionalidad/algo
git log --oneline

Verás el commit portado y el original conviviendo en el historial de main, diciendo lo mismo dos veces. Si el conflicto se resolvió de forma distinta, además habrá conflictuado al fusionar. Ese es exactamente el precio del cherry-pick prematuro.

Solución 3:

mkdir /tmp/practica-agrupar && cd /tmp/practica-agrupar
git init -b main
echo "base" > f.txt && git add . && git commit -m "Base"

git switch -c origen
echo "uno" > uno.txt && git add . && git commit -m "Uno"
echo "dos" > dos.txt && git add . && git commit -m "Dos"
echo "tres" > tres.txt && git add . && git commit -m "Tres"
echo "cuatro" > cuatro.txt && git add . && git commit -m "Cuatro"

git log --oneline origen
8c4f1e7 Cuatro
3b9d6a2 Tres
f51e8c4 Dos
a27c9f3 Uno
1d6b4e8 Base
git switch main
git cherry-pick -n a27c9f3^..3b9d6a2
git status --short
A  dos.txt
A  tres.txt
A  uno.txt
git commit -m "Portar los tres primeros pasos como un único cambio"
git show --stat HEAD
commit 6e2d8b5...
    Portar los tres primeros pasos como un único cambio

 dos.txt  | 1 +
 tres.txt | 1 +
 uno.txt  | 1 +
 3 files changed, 3 insertions(+)

Fíjate en el rango: a27c9f3^..3b9d6a2 incluye Uno, Dos y Tres. Sin el ^ habrías portado solo Dos y Tres.

Conclusión

git cherry-pick es la herramienta de precisión del módulo. Lo esencial:

  • Copia el cambio de un commit sobre tu rama actual creando un commit nuevo con otro hash. Conserva el mensaje, el autor y la fecha de autoría; tú pasas a ser el confirmador.
  • Acepta commits sueltos y rangos, con la trampa habitual de que A..B excluye A y A^..B no. Los commits de fusión quedan fuera de los rangos.
  • -x deja constancia del origen y es imprescindible al portar a ramas de mantenimiento públicas; -n permite acumular varios commits y confirmarlos como uno; -e edita el mensaje y -s añade el sign-off.
  • Los conflictos se resuelven como siempre (lección 03-05) y se sale con --continue, --skip o --abort. Aquí ours y theirs NO están invertidos: la inversión era cosa del rebase.
  • Los casos legítimos son dos: llevar una corrección a una rama que nunca se fusionará con el origen (mantenimiento, versiones antiguas), y rescatar un commit de una rama que se va a abandonar.
  • El precio del abuso son los duplicados: si copias un commit de una rama que después fusionas, el mismo cambio acaba dos veces en el historial y, en el peor caso, aplicado dos veces.
  • git cherry -v y git log --cherry-mark/--cherry-pick detectan cambios equivalentes comparando el patch-id, y son la forma de saber qué queda realmente por portar.
  • Si las dos ramas van a juntarse, no copies: fusiona.

Lo que viene

Las tres lecciones anteriores han manipulado commits: reaplicándolos, reorganizándolos, copiándolos. Todas parten de la misma premisa: que el trabajo ya está confirmado.

Pero el día a día tiene un problema distinto y muy frecuente. Estás a mitad de algo, con el fichero medio escrito y nada confirmable, y llega una urgencia que hay que atender ahora. No quieres confirmar un wip (aunque sea corregible con lo aprendido en 05-02), no quieres perder lo hecho, y necesitas el directorio limpio para cambiar de rama.

Git tiene un cajón para eso, y lo llevamos prometiendo desde la lección 03-02: git stash. Lo abrimos en la lección 05-04: Guardando Cambios Temporales.

Dominando Git: De Principiante a Avanzado

Módulo 1: Introducción a Git

Módulo 2: Operaciones Básicas de Git

Módulo 3: Ramas y Fusión

Módulo 4: Trabajando con Repositorios Remotos

Módulo 5: Operaciones Avanzadas de Git

Módulo 6: Herramientas y Técnicas de Git

Módulo 7: Estrategias de Colaboración y Flujo de Trabajo

Módulo 8: Mejores Prácticas y Consejos de Git

Módulo 9: Solución de Problemas y Depuración

Módulo 10: Git en el Mundo Real

© Copyright 2026. Todos los derechos reservados