git cherry-pick
Aprende el comando git cherry-pick para copiar commits individuales de una rama a otra. Opciones, manejo de conflictos y ejemplos.
Qué hace git cherry-pick
El comando git cherry-pick toma el cambio introducido por uno o más commits existentes y lo vuelve a aplicar en tu rama actual como un nuevo commit. Mientras que git merge y git rebase mueven líneas enteras de historial a la vez, cherry-pick te permite tomar un único commit y colocarlo exactamente donde lo necesitas.
Esta página explica cómo funciona cherry-pick internamente, cómo seleccionar un commit o un rango, las opciones que realmente usarás, cómo resolver conflictos y cuándo usar cherry-pick en lugar de merge o git revert.
Cómo funciona
Un commit es una instantánea, pero cherry-pick lo trata como un parche: calcula la diferencia entre el commit y su padre, luego aplica esa diferencia al extremo de tu rama actual y registra un nuevo commit. El nuevo commit conserva el mensaje, el autor y la fecha originales, pero obtiene un nuevo hash y un nuevo padre porque ahora vive en un lugar diferente del historial.
Esa diferencia es el modelo mental clave: cherry-pick copia un cambio, no lo mueve. El commit de origen permanece exactamente donde estaba en su rama original.
git switch main
git cherry-pick a1b2c3dEl cambio del commit a1b2c3d ahora está en main como un commit nuevo.
Un ejemplo práctico
Supón que un hotfix fue confirmado en feature pero realmente pertenece a main. Primero encuentra el hash del commit con git log:
git switch feature
git log --oneline
# d9ae654 fix login redirect
# 7c1a902 work in progress
# fa42ab5 baseAhora cambia a main y copia solo ese commit:
git switch main
git cherry-pick d9ae654[main 02bbf3e] fix login redirect
1 file changed, 1 insertion(+)Observa el nuevo hash 02bbf3e — el fix ahora está en main como un commit completamente nuevo, mientras que d9ae654 sigue existiendo sin cambios en feature.
Seleccionar un rango de commits
Puedes aplicar varios commits de una sola vez. Un rango copia todos los commits después del primero hasta el último incluido:
git cherry-pick a1b2c3d..f4e5d6cEsto excluye el propio a1b2c3d. Para que el rango sea inclusivo del commit inicial, añade el sufijo ^ para que el rango comience en su padre:
git cherry-pick a1b2c3d^..f4e5d6cLos commits se aplican uno por uno, en orden; si alguno genera conflicto, cherry-pick se detiene en ese commit para que puedas resolverlo antes de continuar.
Opciones comunes
| Comando | Descripción |
|---|---|
git cherry-pick <commit> | Aplica el cambio de <commit> como un nuevo commit en la rama actual. |
git cherry-pick -n <commit> | Aplica el cambio pero no confirma, dejándolo en el área de preparación para que puedas revisarlo o modificarlo antes de confirmar. |
git cherry-pick -x <commit> | Añade una línea (cherry picked from commit …) al mensaje — útil en ramas públicas para que otros puedan rastrear el origen. |
git cherry-pick -e <commit> | Abre tu editor para que puedas cambiar el mensaje del commit antes de que se registre. |
git cherry-pick --continue | Reanuda la operación después de resolver los conflictos. |
git cherry-pick --skip | Omite el commit actual (por ejemplo, cuando su cambio ya está presente) y continúa. |
git cherry-pick --abort | Cancela la operación y restaura la rama a su estado original. |
Con -x el mensaje registrado tiene este aspecto:
fix login redirect
(cherry picked from commit d9ae65426adbde425c3e386a32297e9e833d8816)Manejo de conflictos
Si el cambio no se aplica limpiamente, cherry-pick se detiene de forma similar a como lo hace un merge y deja marcadores de conflicto en los archivos afectados. Verás:
CONFLICT (content): Merge conflict in app.js
error: could not apply d9ae654... fix login redirect
hint: ... fix conflicts and then run "git cherry-pick --continue".Resuelve los archivos en conflicto manualmente, prepáralos con git add y luego continúa:
git add app.js
git cherry-pick --continueEn este punto hay tres vías de escape disponibles:
git cherry-pick --continue— termina después de resolver los conflictos.git cherry-pick --skip— descarta el commit actual y pasa al siguiente del rango.git cherry-pick --abort— cancela todo y devuelve la rama al punto de partida.
Usa git status en cualquier momento para ver qué archivos siguen en conflicto.
Cuándo usarlo
Cherry-pick brilla cuando:
- Un fix aterrizó en la rama equivocada y lo necesitas en otro lugar.
- Estás haciendo backporting de un parche a una rama de versión o de mantenimiento.
- Quieres un único commit de una rama de característica sin hacer merge de todo.
Cherry-pick vs. merge, rebase y revert
| Objetivo | Usa |
|---|---|
| Copiar uno (o algunos) commits específicos a otra rama | git cherry-pick |
| Integrar el historial completo de una rama | git merge |
| Mover los commits de una rama a una nueva base | git rebase |
| Deshacer un commit registrando un commit opuesto | git revert |
Consideraciones importantes
- Duplicados en historial compartido. Hacer cherry-pick en una rama que luego se fusionará de vuelta con la de origen crea dos commits con el mismo cambio. Git suele ser suficientemente inteligente para omitir el duplicado al hacer merge, pero puede complicar el historial — prefiere merge o rebase cuando quieras la rama completa.
- Resultados vacíos. Si el cambio ya está presente en el destino, cherry-pick se detiene con
The previous cherry-pick is now empty. Usagit cherry-pick --skippara continuar, o--abortpara cancelar. - Nuevo hash, no el original. Como el commit se vuelve a crear, su hash cambia. Añade
-xpara que el mensaje registre de dónde proviene.