git cherry-pick
Aplicar los cambios de commits concretos sobre la rama actual
El comando 'git cherry-pick' aplica los cambios introducidos por uno o varios commits existentes sobre la rama actual y crea un commit nuevo por cada uno. A diferencia de merge o rebase, que trabajan con ramas enteras, cherry-pick te deja copiar commits concretos de forma selectiva. Es muy valioso para llevar hotfixes a ramas de release, recuperar commits perdidos o traer funcionalidades concretas de una rama a otra sin integrarlo todo. Cada commit copiado con cherry-pick recibe un SHA nuevo: es una copia, no un traslado. Cherry-pick es quirúrgico y preciso, y te da un control fino sobre qué cambios llegan a tu rama.
Sinopsis
git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff] [-S[<keyid>]] <commit>...
git cherry-pick (--continue | --skip | --abort | --quit)Opciones
Elegir la opción adecuada
git cherry-pick frente a comandos parecidos
Saber cuándo usar cherry-pick en lugar de merge, rebase o revert
| Comando | Aspecto | Cherry-pick | Otro comando |
|---|---|---|---|
Scope | Solo commits concretos | Merge: la rama entera / Rebase: toda la rama | |
Creates new commits | Sí: SHA nuevo, mismo contenido | Merge: commit de merge / Rebase: lo reescribe todo | |
Original stays | Sí: el original no se toca | Merge: sí / Rebase: huérfano | |
Use case | Backports, portar de forma selectiva | Integrar ramas completas | |
History effect | Crea cambios duplicados | Lo conserva o lo hace lineal | |
Conflicts | Por commit durante el pick | En el punto de merge o por cada commit del rebase |
Ejemplos de flujos de trabajo
git checkout release-1.0Cambiarse a la rama de release
git log main --onelineEncontrar el hash del commit del arreglo
git cherry-pick -x abc123Aplicar el arreglo con la referencia de origen
git push origin release-1.0Subir el arreglo portado
git checkout mainCambiarse a la rama main
git log feature --onelineRevisar los commits de la rama de funcionalidad
git cherry-pick abc123 def456Elegir solo los commits listos
git push origin mainSubir los commits elegidos
git reflogEncontrar el hash del commit en el reflog
git checkout mainCambiarse a la rama de destino
git cherry-pick abc123Aplicar el commit huérfano
git checkout target-branchCambiarse a la rama de destino
git cherry-pick A^..CAplicar los commits de A a C (incluidos)
git log --onelineComprobar que los commits se aplicaron
Solución de problemas
"commit is a merge but no -m option was given"
Causa: Intentas hacer cherry-pick de un commit de merge sin indicar qué padre
Usa -m 1 o -m 2 para indicar el padre de la línea principal
git cherry-pick -m 1 <merge-commit>Conflictos durante el cherry-pick
Causa: Los cambios chocan con tu rama actual
Resuelve los conflictos en los archivos, haz git add y luego git cherry-pick --continue. O cancela con --abort
git add <resolved-files> && git cherry-pick --continue"The previous cherry-pick is now empty"
Causa: Los cambios del commit ya existen en tu rama
Ejecuta 'git commit --allow-empty' para registrarlo igualmente, o 'git cherry-pick --skip' para saltarlo
git cherry-pick --skipEl cherry-pick creó commits duplicados
Causa: Los mismos cambios existen ahora como commits distintos en ramas distintas
Es el comportamiento esperado. Usa la opción -x para dejar constancia de la relación
git cherry-pick -x <commit>Se hizo cherry-pick del commit equivocado
Causa: Elegiste el SHA de commit equivocado
Si no se ha subido: git reset --hard HEAD~1. Si ya se subió: haz git revert del commit copiado
git reset --hard HEAD~1El cherry-pick parece no tener efecto
Causa: Puede que el commit esté vacío o que sus cambios ya estuvieran aplicados
Revisa git diff HEAD~1 para ver los cambios reales
git diff HEAD~1Consejos y trampas
Buenas prácticas
- ✓Usa -x en los backports para añadir la referencia '(cherry picked from commit ...)' al mensaje del commit
- ✓Haz cherry-pick en orden cronológico: los commits dependientes deben aplicarse del más antiguo al más reciente para evitar conflictos
- ✓Mejor merge en ramas compartidas: cherry-pick crea commits duplicados, mientras que merge conserva el historial
- ✓Prueba después del cherry-pick: el commit puede funcionar en su contexto original y fallar en el nuevo
- ✓Documenta los cherry-picks en los mensajes con la opción -e para explicar por qué se copió el commit
- ✓Usa --no-commit para combinar picks relacionados en un único commit más limpio
- ✓Plantéate usar git cherry en lugar de log para encontrar commits que aún no se han aplicado
- ✓En los backports, incluye siempre el hash del commit original en el mensaje para poder rastrearlo
Errores comunes
- ✗Olvidar -m en los commits de merge. Hacer cherry-pick de un commit de merge sin '-m 1' o '-m 2' falla: debes indicar respecto a qué padre calcular el diff.
- ✗No preparar los archivos resueltos antes de --continue. Tienes que ejecutar 'git add' sobre los archivos resueltos antes de 'git cherry-pick --continue'.
- ✗Esperar el mismo hash de commit. Cherry-pick crea commits NUEVOS con SHA nuevos: copia cambios, no mueve commits.
- ✗Hacer cherry-pick de commits ya aplicados. Provoca conflictos o commits vacíos: compruébalo antes con 'git log'.
- ✗Elegir los commits en el orden equivocado. Los commits dependientes deben tomarse del más antiguo al más reciente; si no, tendrás conflictos.
- ✗Usar cherry-pick en ramas públicas crea commits duplicados cuando otros tienen el original: mejor merge en ramas compartidas.
Preguntas frecuentes
No. Cherry-pick crea un commit NUEVO con los mismos cambios pero un SHA distinto. El commit original se queda donde estaba.
El hash de un commit de Git depende del contenido, el padre, el autor, la fecha y el mensaje. Cherry-pick conserva el autor y la fecha de autoría, pero el padre y la fecha del committer cambian, así que el hash cambia aunque los cambios sean idénticos.
¡Sí! Enuméralos: git cherry-pick A B C, o usa rangos: git cherry-pick A^..C (incluye A y C).
Usa la opción -m: git cherry-pick -m 1 <merge-commit>. El número indica qué padre es la línea principal (normalmente 1).
A..B excluye A (los commits posteriores a A hasta B). A^..B incluye A (los commits de A a B, ambos incluidos).
Si no se ha subido: git reset --hard HEAD~1. Si ya se subió: git revert <commit> para crear un commit que lo deshaga.
Cherry-pick para commits concretos. Rebase para mover ramas enteras. Si necesitas la mayoría de los commits de una rama, rebase es más limpio.